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.
Sfida
MedioTieni 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 classeStateMachinecon una proprietà pubblicaCurrentche solo la macchina può impostare, un metodoChangeState(IState next)che esegue Exit dello stato precedente e poi Enter del nuovo stato, e un metodoTick()che esegue Tick dello stato corrente. - Il giocatore richiede il proprio stato a ogni frame, quindi
ChangeStatenon fa nulla se lo stato passato è già quello corrente: né Exit né Enter. - In
Player.cs, aggiungi un campoStateMachinechiamatomachine. 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
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
1Componenti, non gerarchie
Componenti piccoliUno script base per i nemiciComponenti astrattiComponenti che collaboranoRiepilogo: torretta modulare4Dati serializzati
Classi serializzabiliListe nell'InspectorEnum nell'InspectorRiepilogo: tabella del bottino7Macchine a stati
Gli stati come classiUna macchina a statiTransizioniIntelligenze dei nemiciRiepilogo: stati della porta10Progetto: Sopravvissuto nell’arena
L’eroeTipi di nemici5ScriptableObjects
Asset di datiStatistiche delle armiImpostazioni condiviseOndate come datiRiepilogo: database degli oggetti