Menu
CoddyTech

Una macchina a stati

Fa parte della sezione Architettura dei giochi in Unity del percorso Unity di Coddy. Lezione 29 di 50.

Il metodo SetState del Beacon sarebbe uguale in ogni oggetto con stati: una torretta, un nemico, una porta. Quel codice può stare in una classe a sé, una macchina a stati, che conserva lo stato corrente e lo cambia. Ogni oggetto crea una macchina e la richiama, invece di ripetere il codice:

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();
    }
}

La prima chiamata a ChangeState non ha uno stato da lasciare: Current è null e ?. salta la chiamata a Exit. La sezione 1 avvertiva che ?. non rileva i null simulati di Unity; questo riguarda gli oggetti Unity distrutti, mentre gli stati sono normali oggetti C#, quindi qui ?. è sicuro. Current ha un private set, quindi nessuno script può sostituire lo stato senza passare da ChangeState e dai suoi metodi Exit ed Enter.

L'ordine all'interno di ChangeState è importante ogni volta che due stati modificano la stessa cosa. Exit annulla ciò che ha modificato il vecchio stato, poi Enter configura quello nuovo, così l'ultimo a intervenire è il nuovo stato. Se il metodo Enter di DarkState spegnesse la lampada e venisse eseguito prima di Exit di BlinkState, quest'ultimo riaccenderebbe la lampada nello stato oscuro. Anche StateMachine è una normale classe: il beacon, una torretta e un nemico ne creano ciascuno una propria con new e ne chiamano Tick dal proprio Update.

challenge icon

Sfida

Medio

Tieni premuto Space per muoverti furtivamente. WalkState e SneakState sono già pronti in PlayerStates.cs: i loro metodi Enter e Exit registrano ciò che succede (Walk: enter, Sneak: exit...), mentre Tick chiama Move() del giocatore. Scrivi la macchina che li gestisce.

  • In StateMachine.cs, scrivi una semplice classe StateMachine con una proprietà pubblica Current che solo la macchina può impostare, un metodo ChangeState(IState next) che esegue Exit dello stato precedente e poi Enter del nuovo stato, e un metodo Tick() che esegue Tick dello stato corrente.
  • Il giocatore richiede il proprio stato a ogni frame, quindi ChangeState non fa nulla se lo stato passato è già quello corrente: né Exit né Enter.
  • In Player.cs, aggiungi un campo StateMachine chiamato machine. In Start, crea la macchina e i due stati (entrambi ricevono il giocatore) e avvia la camminata. In Update, passa allo stato furtivo mentre tieni premuto Space e a quello di camminata altrimenti, poi esegui Tick sulla macchina.

Premi Play, cammina, tieni premuto Space e continua a camminare, poi premi Check.

Provalo tu

// StateMachine: Current, ChangeState e Tick
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Architettura dei giochi in Unity