Menu
CoddyTech

Битва с боссом

Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 64 из 64.

Каменный голем охраняет выход из арены. Он топает в вашу сторону, а когда вы подходите близко, на секунду поднимает кулаки и обрушивает их на землю, нанося вам урон, если вы всё ещё рядом. После удара он отдыхает, и только тогда ваш меч может причинить ему вред: его каменная кожа не чувствует ударов, пока он идёт или готовится к удару. По цвету видно, что он делает: серый, когда идёт, красный, когда готовится к удару, голубой, когда отдыхает. Снизьте его здоровье до 0, и ворота откроются. Полоска в верхней части экрана обновляется после каждого удара.

Напишите мозг голема в виде машины состояний, создав класс для каждого состояния: Boss, а также ChaseState, WindupState и RestState в BossStates.cs. Игрок, полоска здоровья, ворота, IState, StateMachine и IDamageable уже готовы, а Boss уже создаёт свои состояния и обновляет машину.

challenge icon

Задание

Сложно

Напиши состояния голема в BossStates.cs.

  1. ChaseState: Tint(Color.gray); двигайся к игроку со скоростью speed; при приближении на расстояние slamRange начинай подготовку к удару.
  2. WindupState: Tint(Color.red); через windupTime выведи в журнал Slam!, нанеси игроку в радиусе урон в размере slamDamage, затем переходи в состояние отдыха.
  3. RestState: Tint(Color.cyan); через restTime преследуй игрока.
  4. Boss.TakeDamage учитывает урон только в состоянии rest: вычти указанное количество, вызови событие HealthChanged, при значении 0 вызови Fall().

Нажми «Играть» и атакуй, пока он отдыхает. Затем нажми «Проверить».

Попробуйте сами

using System;
using UnityEngine;
using UnityEngine.Events;

public class Boss : MonoBehaviour, IDamageable
{
    public Transform player;
    public float speed = 2f;
    public float slamRange = 2.5f;
    public float windupTime = 1f;
    public float restTime = 2f;
    public int slamDamage = 2;
    public int maxHealth = 6;

    public event Action<int, int> HealthChanged;
    public UnityEvent onDefeated;

    public StateMachine machine;
    public IState chase;
    public IState windup;
    public IState rest;

    private int health;

    void Awake()
    {
        health = maxHealth;
        machine = new StateMachine();
        chase = new ChaseState(this);
        windup = new WindupState(this);
        rest = new RestState(this);
    }

    void Start()
    {
        HealthChanged?.Invoke(health, maxHealth);
        machine.ChangeState(chase);
    }

    void Update()
    {
        machine.Tick();
    }

    public void TakeDamage(int amount)
    {
        // Удары засчитываются только во время отдыха: уменьшите здоровье на amount, вызовите HealthChanged и Fall() при 0
    }

    // Готово: голем падает, ворота открываются, и голем покидает арену.
    void Fall()
    {
        Debug.Log("The golem falls");
        onDefeated.Invoke();
        gameObject.SetActive(false);
    }

    // Расстояние до игрока по поверхности земли.
    public float PlayerDistance()
    {
        Vector3 d = player.position - transform.position;
        d.y = 0f;
        return d.magnitude;
    }

    // Серый, пока он идёт; красный, пока готовится к удару; голубой, пока отдыхает.
    public void Tint(Color color)
    {
        GetComponent<Renderer>().material.color = color;
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Архитектура игр в Unity

Потренируйтесь самостоятельно: Песочница Unity