Menu
CoddyTech

Ein Zustandsautomat

Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 37 von 64.

Die Methode SetState des Leuchtfeuers wäre bei jedem Objekt mit Zuständen gleich: einem Geschützturm, einem Gegner, einer Tür. Dieser Code kann in einer eigenen Klasse stehen, einer Zustandsmaschine, die den aktuellen Zustand speichert und ihn ändert. Jedes Objekt erstellt eine Maschine und ruft sie auf, statt den Code zu wiederholen:

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

Beim ersten Aufruf von ChangeState gibt es keinen Zustand, den man verlassen könnte: Current ist null, und ?. überspringt den Aufruf von Exit. In Abschnitt 1 wurde darauf hingewiesen, dass ?. Unitys falsches null nicht erkennt; das betrifft zerstörte Unity-Objekte. Da es sich bei den Zuständen um einfache C#-Objekte handelt, ist ?. hier sicher. Current hat einen private set, sodass kein Skript den Zustand wechseln kann, ohne ChangeState und dessen Exit und Enter zu durchlaufen.

Die Reihenfolge innerhalb von ChangeState ist wichtig, wenn zwei Zustände dieselbe Sache beeinflussen. Exit macht rückgängig, was der alte Zustand geändert hat, dann richtet Enter den neuen Zustand ein, sodass der neue Zustand das letzte Wort hat. Wenn Enter eines DarkState die Lampe ausgeschaltet hätte und vor Exit von BlinkState ausgeführt worden wäre, hätte dieses Exit die Lampe im dunklen Zustand wieder eingeschaltet. Auch die StateMachine ist eine einfache Klasse: Das Leuchtfeuer, ein Geschützturm und ein Gegner erstellen jeweils mit new ihre eigene Instanz und rufen deren Tick in ihrem Update auf.

challenge icon

Aufgabe

Mittel

Führe die Zustände des Spielers mit einer Zustandsmaschine aus.

  1. Schreibe in StateMachine.cs public class StateMachine mit public IState Current { get; private set; } und einer Tick()-Methode, die den aktuellen Zustand aktualisiert.
  2. ChangeState(IState next) ignoriert den aktuellen Zustand; andernfalls Exit aufrufen, Current setzen und Enter aufrufen.
  3. Player: In Start werden machine, walk und sneak erstellt und der Gehzustand aktiviert; in Update wird geschlichen, solange die Leertaste gedrückt ist, andernfalls wird gegangen, und danach wird der Zustand aktualisiert.

Drücke „Spielen“ und halte die Leertaste gedrückt: Sneak: enter. Drücke dann „Prüfen“.

Probier es selbst

// StateMachine: Current, ChangeState und Tick

Alle Lektionen in Spielarchitektur in Unity

Übe selbstständig: Unity-Playground