Menu
CoddyTech

Gli stati come classi

Fa parte della sezione Architettura dei giochi in Unity del percorso Unity di Coddy. Lezione 35 di 64.

Lo switch su un enum della sezione 3 mantiene il lavoro di ogni stato in un unico Update. Questo approccio 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 case deve ricordarsi di reimpostare ciò che usa. Il pattern degli stati di C# assegna a ogni stato una classe dedicata e ogni classe implementa la stessa interfaccia. Questo segnalatore stradale lampeggia o resta acceso, e Space alterna le due modalità:

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 classi C# semplici, non MonoBehaviours. Li crei con new e fornisci loro ciò di cui hanno bisogno tramite il costruttore, in questo caso il Renderer della lampada, perché non sono componenti e non possono chiamare GetComponent né mostrare campi nell'Inspector. Unity non chiama nemmeno 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 riporta tutto alla normalità quando lo stato termina: Space può essere premuto mentre la lampada è spenta ed 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, richiede un'altra classe e Update di Beacon non cambia.

challenge icon

Sfida

Medio

Scrivi lo stato di scansione della torretta.

  1. In IState.cs, dichiara public interface IState con void Enter();, void Tick(); e void Exit();.
  2. In TurretStates.cs, scrivi ScanState : IState, passando la testa. Enter: angolo 0, testa Color.green. Tick: fai oscillare l'angolo y locale della testa tra -45 e 45, a 90 gradi al secondo.
  3. Turret: inseriscine uno in Start e aggiornalo con Tick in Update.

Premi «Gioca»: la testa verde oscilla. Poi premi «Verifica».

Provalo tu

using UnityEngine;

// ScanState

Tutte le lezioni di Architettura dei giochi in Unity

Esercitati da solo: Playground Unity