Menu
CoddyTech

Gli stati come classi

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

La gestione degli stati tramite switch della sezione 3 concentra il lavoro di ogni stato in un unico Update. Questa soluzione non è scalabile quando gli stati hanno dati propri: un timer usato da un solo stato finisce per essere un campo di MonoBehaviour, accanto ai campi di tutti gli altri stati, e ogni caso deve ricordarsi di reimpostare ciò che usa. Il pattern state di C# assegna a ogni stato una classe propria e ogni classe implementa un'interfaccia. Questo segnalatore stradale lampeggia o resta acceso, e Space alterna i due stati:

public interface IState
{
    void Enter();
    void Tick();
    void Exit();
}

public class BlinkState : IState
{
    private Renderer lamp;
    private float timer;

    public BlinkState(Renderer lamp)
    {
        this.lamp = lamp;
    }

    public void Enter() { timer = 0f; }

    public void Tick()
    {
        timer += Time.deltaTime;
        if (timer >= 0.5f)
        {
            timer = 0f;
            lamp.enabled = !lamp.enabled;
        }
    }

    public void Exit() { lamp.enabled = true; }
}

public class SteadyState : IState
{
    public void Enter() { }
    public void Tick() { }
    public void Exit() { }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private IState blink;
    private IState steady;
    private IState current;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        SetState(steady);
    }

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

    void SetState(IState next)
    {
        if (current != null) current.Exit();
        current = next;
        current.Enter();
    }
}

Gli stati sono normali classi C#, non MonoBehaviours. Li crei con new e gli passi ciò di cui hanno bisogno tramite il costruttore, qui il Renderer della lampada, perché non sono componenti e non possono chiamare GetComponent né mostrare campi nell'Inspector. Neanche Unity chiama i loro metodi: Beacon è il MonoBehaviour, quindi il suo Update chiama current.Tick() a ogni frame.

Il timer appartiene solo a BlinkState e il suo Enter lo imposta a 0 ogni volta che il segnalatore inizia a lampeggiare. Exit sistema le cose quando lo stato termina: Space può essere premuto mentre la lampada è spenta, e Exit la riaccende, così SteadyState non inizia mai con la lampada spenta. SetState esegue Exit dello stato precedente, poi Enter del nuovo stato. Un terzo stato, come un impulso lento, è un'altra classe, e Update di Beacon non cambia.

challenge icon

Sfida

Medio

Una torretta di guardia protegge il cortile. Le frecce guidano il Player (pronto). Assegna alla torretta due stati, scritti come classi:

  • In IState.cs, dichiara public interface IState con void Enter(), void Tick() e void Exit().
  • In TurretStates.cs, scrivi due classi semplici che lo implementano. ScanState riceve la testa della torretta nel costruttore. Fa oscillare la testa da un lato all'altro: l'angolo y locale della testa si sposta a 90 gradi al secondo tra -45 e 45, partendo da 0 e girando verso l'alto ogni volta che inizia la scansione. Anche il suo Enter colora la testa con Color.green.
  • AlertState riceve la testa e il giocatore. Il suo Enter colora la testa con Color.red e registra Intruder!; il suo Tick gira la testa per rivolgerla verso il giocatore solo attorno all'asse y, senza inclinazione; il suo Exit registra All clear.
  • In Turret.cs, crea entrambi gli stati in Start e avvia la scansione. A ogni fotogramma, passa allo stato di allerta quando il giocatore è più vicino di range (4) alla torretta, e torna alla scansione quando non lo è, quindi esegui il Tick dello stato corrente. Un cambio esegue l'Exit del vecchio stato, quindi l'Enter del nuovo.

Premi Play, avvicinati alla torretta e poi allontanati, quindi premi Check.

Provalo tu

using UnityEngine;

// ScanState e AlertState
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