Menu
CoddyTech

Машина состояний

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

Метод SetState у маяка был бы одинаковым для любого объекта с состояниями: турели, противника, двери. Этот код может находиться в отдельном классе — машине состояний, которая хранит текущее состояние и меняет его. Каждый объект создает свою машину и вызывает ее вместо того, чтобы повторять код:

public class StateMachine
{
    public IState Current { get; private set; }

    public void ChangeState(IState next)
    {
        Current?.Exit();
        Current = next;
        Current.Enter();
    }

    public void Tick()
    {
        Current?.Tick();
    }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private StateMachine machine = new StateMachine();
    private IState blink;
    private IState steady;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        machine.ChangeState(steady);
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame) machine.ChangeState(machine.Current == steady ? blink : steady);
        machine.Tick();
    }
}

При первом вызове ChangeState выходить из состояния не нужно: Current равен null, и ?. пропускает вызов Exit. В разделе 1 предупреждалось, что ?. не распознает фиктивный null в Unity; это относится к уничтоженным объектам Unity, а состояния — обычные объекты C#, поэтому здесь ?. безопасен. У Current есть private set, поэтому никакой скрипт не может сменить состояние, не вызвав ChangeState и его Exit и Enter.

Порядок действий внутри ChangeState важен, когда два состояния взаимодействуют с одним и тем же объектом. Exit отменяет изменения, внесенные старым состоянием, а затем Enter настраивает новое, поэтому последнее слово остается за новым состоянием. Если бы Enter состояния DarkState выключал лампу и выполнялся до Exit состояния BlinkState, этот Exit снова включил бы лампу в темном состоянии. StateMachine тоже является обычным классом: маяк, турель и противник каждый создают свою машину с помощью new и вызывают ее Tick из своего Update.

challenge icon

Задание

Средне

Управляйте состояниями игрока с помощью автомата.

  1. В StateMachine.cs напишите public class StateMachine с public IState Current { get; private set; } и методом Tick(), который вызывает Tick текущего состояния.
  2. ChangeState(IState next) игнорирует текущее состояние; иначе вызывает Exit, задаёт Current и вызывает Enter.
  3. Player: в Start создайте machine, walk, sneak и перейдите в состояние ходьбы; в Update переходите в состояние крадущегося движения, пока удерживается Space, иначе — в состояние ходьбы, а затем вызывайте Tick.

Нажмите «Играть» и удерживайте Space: Sneak: enter. Затем нажмите «Проверить».

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

// StateMachine: Current, ChangeState и Tick

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

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