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.
Aufgabe
MittelFühre die Zustände des Spielers mit einer Zustandsmaschine aus.
- Schreibe in
StateMachine.cspublic class StateMachinemitpublic IState Current { get; private set; }und einerTick()-Methode, die den aktuellen Zustand aktualisiert. ChangeState(IState next)ignoriert den aktuellen Zustand; andernfalls Exit aufrufen,Currentsetzen und Enter aufrufen.Player: In Start werdenmachine,walkundsneakerstellt 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
1Komponenten statt Hierarchien
Kleine KomponentenEin Basis-GegnerskriptAbstrakte KomponentenZusammenwirkende KomponentenRückblick: Modulares GeschützRückblick: Zwillingskanone4Serialisierte Daten
Serialisierbare KlassenListen im InspectorEnums im InspectorRückblick: Loot-TabelleRückblick: Beute auswürfeln7Zustandsautomaten
Zustände als KlassenDer AlarmzustandEin ZustandsautomatÜbergängeGegner-KIDer Ritter greift anRückblick: Türzustände2Schnittstellen in Unity
IDamageableSchnittstellen und TryGetComponentGetComponentsZusammenfassung: InteraktionstasteZusammenfassung: Nächstes in Reichweite5ScriptableObjects
Daten-AssetsWaffenwerteGemeinsame EinstellungenDen Wind speichernWellen als DatenRückblick: Item-DatenbankRückblick: Im Shop einkaufen8Wiederverwendbarer Code
ErweiterungsmethodenEin generisches SingletonGenerische HilfsmethodenRückblick: FindNearestÜbe selbstständig: Unity-Playground