Beim Programmieren von In-Game-Entitäten treten Situationen auf, in denen sie unter unterschiedlichen Bedingungen auf unterschiedliche Weise agieren müssen, was auf die Verwendung von
Zuständen hindeutet.
Wenn Sie sich jedoch für Brute Force entscheiden, verwandelt sich der Code schnell in ein Chaos mit vielen verschachtelten if-else-Anweisungen.
Für eine ordnungsgemäße Lösung dieses Problems können Sie das Entwurfsmuster "Status" verwenden. Wir werden ihm dieses Tutorial widmen!
Aus dem Tutorial Sie:
- Lernen Sie die Grundlagen der Statusvorlage in Unity kennen.
- Sie erfahren, was eine Zustandsmaschine ist und wann sie verwendet werden muss.
- Erfahren Sie, wie Sie diese Konzepte verwenden, um die Bewegung Ihres Charakters zu steuern.
Hinweis : Dieses Tutorial richtet sich an fortgeschrittene Benutzer. Es wird davon ausgegangen, dass Sie bereits mit Unity vertraut sind und über durchschnittliche Kenntnisse in C # verfügen. Darüber hinaus verwendet dieses Lernprogramm Unity 2019.2 und C # 7.
An die Arbeit gehen
Projektmaterialien herunterladen. Entpacken Sie die
Zip-Datei und öffnen Sie das Startprojekt in Unity.
Das Projekt enthält mehrere Ordner, die Ihnen den Einstieg erleichtern. Der Ordner
Assets / RW enthält die Ordner
Animationen ,
Materialien ,
Modelle ,
Prefabs ,
Ressourcen ,
Szenen ,
Skripte und
Sounds , die nach den darin enthaltenen Ressourcen benannt sind.
Um das Tutorial zu vervollständigen, arbeiten wir nur mit
Szenen und
Skripten .
Gehen Sie zu
RW / Scenes und öffnen Sie
Main . Im Spielmodus sehen Sie eine Figur in einer Kapuze in einer mittelalterlichen Burg.
Klicken Sie auf "
Abspielen" und beobachten Sie, wie sich die
Kamera an den
Zeichenrahmen anpasst. Momentan gibt es in unserem kleinen Spiel keine Interaktionen, wir werden sie im Tutorial bearbeiten.
Erkunde den Charakter
Wählen Sie in der
Hierarchie Zeichen . Überprüfen Sie den
Inspector . Sie sehen eine
Komponente mit demselben Namen, die die Steuerlogik für
Zeichen enthält.
Öffnen Sie
Character.cs in
RW / Scripts .
Das Skript führt viele Aktionen aus, die meisten sind jedoch für uns nicht wichtig. Beachten wir zunächst die folgenden Methoden.
Move
: Bewegt den Charakter und empfängt Werte vom Typ Gleitgeschwindigkeit als Bewegungsgeschwindigkeit und rotationSpeed
als Winkelgeschwindigkeit.ResetMoveParams
: Diese Methode setzt die Parameter zurück, mit denen die Bewegung und die Winkelgeschwindigkeit des Zeichens animiert werden . Es wird nur zur Reinigung verwendet.SetAnimationBool
: param
Parameter param
animation vom Typ Bool auf value.CheckCollisionOverlap
: Er empfängt einen
Typ Vector3
und gibt ein Vector3
zurück, das bestimmt, ob sich innerhalb des angegebenen Radius vom
Vector3
befinden.TriggerAnimation
: TriggerAnimation
den Animationsparameter des Eingabeparameters param
.ApplyImpulse
: ApplyImpulse
Impuls auf Character an, der dem Eingabeparameter force
Typ Vector3
.
Nachfolgend sehen Sie diese Methoden. In unserem Tutorial sind deren Inhalt und interne Arbeit nicht wichtig.
Was sind Zustandsautomaten?
Eine Zustandsmaschine ist ein Konzept, bei dem ein Container den Zustand von etwas zu einem bestimmten Zeitpunkt speichert. Basierend auf den Eingabedaten kann es abhängig vom aktuellen Status eine Schlussfolgerung geben, die in diesem Prozess in einen neuen Status übergeht. Zustandsautomaten können als
Zustandsdiagramm dargestellt werden . Wenn Sie ein Zustandsdiagramm erstellen, können Sie alle möglichen Zustände des Systems und die Übergänge zwischen ihnen durchdenken.
Zustandsautomaten
Finite State Machines oder
FSM (Finite State Machine) ist eine der vier Hauptfamilien von
Maschinen . Automaten sind abstrakte Modelle einfacher Maschinen. Sie werden im Rahmen der
Automatentheorie - dem theoretischen Zweig der Informatik - untersucht.
Kurzgesagt:
- FSM besteht aus einer endlichen Menge von Bedingungen . Zu jedem Zeitpunkt ist nur einer dieser Zustände aktiv .
- Jeder Zustand bestimmt, in welchen Zustand er als Ausgabe geht, basierend auf der empfangenen Sequenz eingehender Informationen .
- Der Ausgangszustand wird zum neuen aktiven Zustand. Mit anderen Worten, es gibt einen Übergang zwischen Zuständen .
Um dies besser zu verstehen, betrachten Sie den Charakter eines Plattformspiels, das vor Ort ist. Der Charakter befindet sich im
stehenden Zustand. Dies ist sein
aktiver Zustand, bis der Spieler den Knopf drückt, so dass der Charakter springt.
Der Status "
Stehend" kennzeichnet einen Tastendruck als signifikanten
Eingang und wechselt als
Ausgang in den Status "
Springen" .
Angenommen, es gibt eine bestimmte Anzahl solcher Bewegungszustände, und ein Charakter kann sich jeweils nur in einem der Zustände befinden. Dies ist ein Beispiel für FSM.
Hierarchische Zustandsmaschinen
Stellen Sie sich einen Plattformer mit FSM vor, in dem mehrere Zustände eine gemeinsame Physiklogik aufweisen. Sie können sich beispielsweise in den Zuständen
Hocken und
Stehen bewegen und springen. In diesem Fall führen mehrere eingehende Variablen für zwei verschiedene Zustände zur gleichen Verhaltens- und Informationsausgabe.
In einer solchen Situation wäre es logisch, das allgemeine Verhalten an einen anderen Staat zu delegieren. Glücklicherweise kann dies mit
hierarchischen Zustandsautomaten erreicht werden.
In einem hierarchischen FSM gibt es
Unterzustände, die eingehende
Rohdaten an ihre
Unterzustände delegieren . Auf diese Weise können Sie die Größe und Komplexität des FSM unter Beibehaltung seiner Logik elegant reduzieren.
Statusvorlage
In ihrem Buch
Design Patterns: Elemente wiederverwendbarer objektorientierter Software definierten Erich Gamma, Richard Helm, Ralph Johnson und John Vlissidis (
Die Viererbande ) die
Aufgabe der Vorlage State wie folgt:
„Er muss dem Objekt erlauben, sein Verhalten zu ändern, wenn sich sein interner Zustand ändert. In diesem Fall hat das Objekt anscheinend seine Klasse geändert. “
Um dies besser zu verstehen, betrachten Sie das folgende Beispiel:
- Ein Skript, das eingehende Informationen für die Bewegungslogik empfängt, ist an eine Entität im Spiel angehängt.
- Diese Klasse speichert eine aktuelle Statusvariable, die sich einfach auf eine Instanz der Statusklasse bezieht.
- Eingehende Informationen werden an diesen aktuellen Status delegiert, der sie verarbeitet und ein in sich selbst definiertes Verhalten erzeugt. Es behandelt auch die erforderlichen Zustandsübergänge.
Aufgrund der Tatsache, dass sich die
aktuelle Statusvariable zu unterschiedlichen Zeitpunkten auf unterschiedliche
Status bezieht, scheint es, dass sich dieselbe Skriptklasse unterschiedlich verhält. Dies ist das Wesentliche der Vorlage "Status".
In unserem Projekt verhält sich die oben genannte
Zeichenklasse je nach Status unterschiedlich. Aber wir brauchen ihn, um sich zu benehmen!
Im Allgemeinen gibt es drei Schlüsselpunkte für jede Zustandsklasse, die das Verhalten des gesamten Staates ermöglichen:
- Eintrag : Dies ist der Moment, in dem eine Entität in einen Zustand eintritt und Aktionen ausführt, die beim Eintritt in den Zustand nur einmal ausgeführt werden müssen.
- Beenden : Ähnlich wie bei der Eingabe werden hier alle Rücksetzvorgänge ausgeführt, die nur ausgeführt werden müssen, bevor sich der Status ändert.
- Update-Schleife : Hier ist die grundlegende Update-Logik , die in jedem Frame ausgeführt wird. Es kann in mehrere Teile unterteilt werden, z. B. einen Zyklus zum Aktualisieren der Physik und einen Zyklus zum Verarbeiten der Spielereingaben.
Definieren eines Zustands und einer Zustandsmaschine
Gehen Sie zu
RW / Scripts und öffnen Sie
StateMachine.cs .
Die Zustandsmaschine stellt , wie Sie vielleicht vermuten, eine Abstraktion für die Zustandsmaschine bereit. Beachten Sie, dass sich
CurrentState
korrekt in dieser Klasse befindet. Es wird eine Verknüpfung zum aktuellen Status der aktiven Statusmaschine gespeichert.
Um das Konzept des
Status zu definieren,
rufen Sie RW / Scripts auf und öffnen Sie das Skript
State.cs in der IDE.
State ist eine abstrakte Klasse, die wir als
Modell verwenden, aus dem alle
Klassen von Projektstatus abgeleitet werden. Ein Teil des Codes in den Projektmaterialien ist bereits fertig.
DisplayOnUI
zeigt nur den Namen des aktuellen Status in der Bildschirmbenutzeroberfläche an. Sie müssen das interne Gerät nicht kennen. Sie müssen lediglich verstehen, dass es einen Enumerator des Typs
UIManager.Alignment
als Eingabeparameter empfängt, der
Left
oder
Right
. Die Anzeige des Namens des Status im linken oder rechten unteren Teil des Bildschirms hängt davon ab.
Zusätzlich gibt es zwei geschützte Variablen,
character
und
stateMachine
. Die
character
verweist auf eine Instanz der
Character- Klasse, und
stateMachine
verweist auf eine Instanz
der Zustandsmaschine, die dem Zustand zugeordnet ist.
Beim Erstellen einer
stateMachine
bindet der Konstruktor
character
und
stateMachine
.
Jede der vielen Instanzen von
Character
in einer Szene kann einen eigenen Satz von Zuständen und Zustandsautomaten haben.
Fügen Sie State.cs nun die folgenden Methoden
hinzu und speichern Sie die Datei:
public virtual void Enter() { DisplayOnUI(UIManager.Alignment.Left); } public virtual void HandleInput() { } public virtual void LogicUpdate() { } public virtual void PhysicsUpdate() { } public virtual void Exit() { }
Diese virtuellen Methoden definieren die oben beschriebenen Hauptstatuspunkte. Wenn
die Zustandsmaschine einen Übergang zwischen Zuständen durchführt, rufen wir
Exit
für den vorherigen Zustand auf und
Enter
neuen
aktiven Zustand ein .
HandleInput
,
LogicUpdate
und
PhysicsUpdate
definieren zusammen
eine Aktualisierungsschleife .
HandleInput
verarbeitet die Player-Eingabe.
LogicUpdate
verarbeitet grundlegende Logik, während
PhyiscsUpdate
Logik- und Physikberechnungen verarbeitet.
Öffnen
Sie nun
StateMachine.cs erneut, fügen Sie die folgenden Methoden hinzu und speichern Sie die Datei:
public void Initialize(State startingState) { CurrentState = startingState; startingState.Enter(); } public void ChangeState(State newState) { CurrentState.Exit(); CurrentState = newState; newState.Enter(); }
Initialize
konfiguriert den Zustandsautomaten, indem
CurrentState
auf
startingState
und die
Enter
dafür
CurrentState
. Dies initialisiert die Zustandsmaschine und setzt zum ersten Mal den aktiven Zustand.
ChangeState
behandelt
ChangeState
. Es ruft
Exit
für den alten
CurrentState
bevor die Referenz durch
newState
. Am Ende wird
Enter
für
newState
.
So setzen wir den
Zustand und die
Zustandsmaschine .
Bewegungszustände erstellen
Schauen Sie sich das folgende Zustandsdiagramm an, in dem die verschiedenen
Bewegungszustände der In-Game-Essenz
des Spielers dargestellt sind. In diesem Abschnitt implementieren wir die Vorlage "Status" für die in der
FSM- Abbildung gezeigte
Bewegung :
Achten Sie auf die Bewegungszustände
Stehen ,
Ducken und
Springen sowie darauf, wie die eingehenden Daten Übergänge zwischen den Zuständen verursachen. Dies ist eine hierarchische FSM, in der
Grounded ein Unterzustand für die
Unterzustände Ducking und
Standing ist .
Kehren Sie zu Unity zurück und gehen Sie zu
RW / Scripts / States . Dort finden Sie mehrere C # -Dateien mit Namen, die auf
State enden.
Jede dieser Dateien definiert eine Klasse, von denen jede von
State
geerbt wird. Daher definieren diese Klassen die Zustände, die wir im Projekt verwenden werden.
Öffnen Sie nun
Character.cs aus dem
RW / Scripts- Ordner.
#region Variables
über die Datei
#region Variables
und fügen Sie den folgenden Code hinzu:
public StateMachine movementSM; public StandingState standing; public DuckingState ducking; public JumpingState jumping;
Diese
movementSM
bezieht sich auf eine Zustandsmaschine, die die Bewegungslogik für die
Character
Instanz verarbeitet. Wir haben auch Links zu drei Zuständen hinzugefügt, die wir für jede Art von Bewegung implementieren.
Gehen
#region MonoBehaviour Callbacks
in derselben Datei zu
#region MonoBehaviour Callbacks
. Fügen Sie die folgenden
MonoBehaviour- Methoden hinzu und speichern Sie sie
private void Start() { movementSM = new StateMachine(); standing = new StandingState(this, movementSM); ducking = new DuckingState(this, movementSM); jumping = new JumpingState(this, movementSM); movementSM.Initialize(standing); } private void Update() { movementSM.CurrentState.HandleInput(); movementSM.CurrentState.LogicUpdate(); } private void FixedUpdate() { movementSM.CurrentState.PhysicsUpdate(); }
- In
Start
Code eine Instanz der Zustandsmaschine und weist sie movementSM
. Außerdem werden verschiedene Bewegungszustände instanziiert. Bei der Erstellung der einzelnen Bewegungszustände übergeben wir unter Verwendung des this
sowie der movementSM
Instanz Verweise auf die Character
Instanz. Am Ende rufen wir Initialize
for movementSM
und übergeben Standing
als Ausgangszustand. - In der
Update
Methode rufen wir HandleInput
und LogicUpdate
für den CurrentState
der movementSM
Maschine auf. Ebenso FixedUpdate
wir in FixedUpdate
PhysicsUpdate
für den CurrentState
der movementSM
Maschine auf. Im Wesentlichen delegiert dies Aufgaben an einen aktiven Status. Dies ist die Bedeutung der Vorlage "Status".
Jetzt müssen wir das Verhalten in jedem der Bewegungszustände einstellen. Machen Sie sich bereit, es wird eine Menge Code geben!
Stehend fest
Kehren Sie im Projektfenster zu
RW / Scripts / States zurück.
Öffnen Sie
Grounded.cs, und beachten Sie, dass diese Klasse über einen Konstruktor verfügt, der dem
State
Konstruktor entspricht. Das ist logisch, weil diese Klasse davon erbt. Sie werden dasselbe in allen anderen Staatsklassen sehen.
Fügen Sie den folgenden Code hinzu:
public override void Enter() { base.Enter(); horizontalInput = verticalInput = 0.0f; } public override void Exit() { base.Exit(); character.ResetMoveParams(); } public override void HandleInput() { base.HandleInput(); verticalInput = Input.GetAxis("Vertical"); horizontalInput = Input.GetAxis("Horizontal"); } public override void PhysicsUpdate() { base.PhysicsUpdate(); character.Move(verticalInput * speed, horizontalInput * rotationSpeed); }
Folgendes passiert hier:
- Wir definieren eine der in der Elternklasse definierten virtuellen Methoden neu. Um die gesamte Funktionalität des übergeordneten Elements beizubehalten, rufen wir die
base
mit demselben Namen für jede überschriebene Methode auf. Dies ist eine wichtige Vorlage, die wir weiterhin verwenden werden. - Die nächste Zeile,
Enter
setzt horizontalInput
und verticalInput
ihre Standardwerte. - Innerhalb von
Exit
rufen wir, wie oben erwähnt, die ResetMoveParams
Methode des
, um sie zurückzusetzen, wenn Sie in einen anderen Status wechseln. - In der
HandleInput
Methode zwischenspeichern die Variablen horizontalInput
und verticalInput
HandleInput
Werte der horizontalen und vertikalen Eingabeachse. Dank dessen kann der Spieler den Charakter mit den Tasten W , A , S und D steuern . - Bei
PhysicsUpdate
wir Move
und übergeben die Variablen horizontalInput
und verticalInput
multipliziert mit den entsprechenden Geschwindigkeiten. In der variablen speed
die Bewegungsgeschwindigkeit und in rotationSpeed
die Winkelgeschwindigkeit gespeichert.
Öffnen Sie nun
Standing.cs und achten Sie darauf, dass es von
Grounded
erbt. Es ist passiert, weil
Standing , wie wir oben sagten, ein Substate für
Grounded ist . Es gibt verschiedene Möglichkeiten, diese Beziehung zu implementieren. In diesem Lernprogramm wird jedoch die Vererbung verwendet.
Fügen Sie die folgenden
override
und speichern Sie das Skript:
public override void Enter() { base.Enter(); speed = character.MovementSpeed; rotationSpeed = character.RotationSpeed; crouch = false; jump = false; } public override void HandleInput() { base.HandleInput(); crouch = Input.GetButtonDown("Fire3"); jump = Input.GetButtonDown("Jump"); } public override void LogicUpdate() { base.LogicUpdate(); if (crouch) { stateMachine.ChangeState(character.ducking); } else if (jump) { stateMachine.ChangeState(character.jumping); } }
- In
Enter
konfigurieren wir die von Grounded
geerbten Variablen. Wenden Sie die MovementSpeed
und RotationSpeed
Charakters auf speed
und rotationSpeed
. Dann beziehen sie sich jeweils auf die normale Bewegungsgeschwindigkeit und die Winkelgeschwindigkeit, die für das Wesen des Charakters bestimmt sind.
Darüber hinaus werden Variablen zum Speichern von crouch
Eingaben und jump
auf false zurückgesetzt. - In
HandleInput
speichern die Variablen HandleInput
und jump
die Eingaben des Spielers für Kniebeugen und Sprünge. Wenn der Spieler in der Hauptszene die Umschalttaste drückt , wird die Hocke auf true gesetzt. Ebenso kann ein Spieler mit der Leertaste jump
. - In
LogicUpdate
überprüfen wir die Variablen LogicUpdate
und jump
vom Typ bool
. Wenn crouch
true ist, ändert sich movementSM.CurrentState
in character.ducking
. Wenn jump
true ist, ändert sich der Status in character.jumping
.
Speichern und montieren Sie das Projekt und klicken Sie dann auf
Wiedergabe . Mit den Tasten
W ,
A ,
S und
D können Sie sich in der Szene bewegen
. Wenn Sie versuchen, die
Umschalt- oder Leertaste zu drücken, tritt ein unerwartetes Verhalten auf, da die entsprechenden Status noch nicht implementiert sind.
Versuchen Sie, sich unter den Tischobjekten zu bewegen. Sie werden sehen, dass dies aufgrund der Höhe des Colliders des Charakters nicht möglich ist. Damit der Charakter dies tun kann, müssen Sie das Verhalten der Hocke hinzufügen.
Wir klettern unter den Tisch
Öffnen Sie das Skript
Ducking.cs . Beachten Sie, dass
Ducking
aus den gleichen Gründen wie
Standing
auch von der
Grounded
Klasse erbt. Fügen Sie die folgenden
override
und speichern Sie das Skript:
public override void Enter() { base.Enter(); character.SetAnimationBool(character.crouchParam, true); speed = character.CrouchSpeed; rotationSpeed = character.CrouchRotationSpeed; character.ColliderSize = character.CrouchColliderHeight; belowCeiling = false; } public override void Exit() { base.Exit(); character.SetAnimationBool(character.crouchParam, false); character.ColliderSize = character.NormalColliderHeight; } public override void HandleInput() { base.HandleInput(); crouchHeld = Input.GetButton("Fire3"); } public override void LogicUpdate() { base.LogicUpdate(); if (!(crouchHeld || belowCeiling)) { stateMachine.ChangeState(character.standing); } } public override void PhysicsUpdate() { base.PhysicsUpdate(); belowCeiling = character.CheckCollisionOverlap(character.transform.position + Vector3.up * character.NormalColliderHeight); }
- In der
Enter
Parameter, der das Umschalten der Kniebeugenanimation bewirkt, auf "geduckt" gesetzt, wodurch die Kniebeugenanimation aktiviert wird. Den Eigenschaften character.CrouchSpeed
und character.CrouchRotationSpeed
die Werte für speed
und rotation
zugewiesen, die die Bewegung und Winkelgeschwindigkeit des Zeichens beim Bewegen in einer Hocke zurückgeben .
Nächstes character.CrouchColliderHeight
legt die Größe des Colliders des Zeichens fest, der beim Hocken die gewünschte Collider-Höhe zurückgibt. Am Ende wird belowCeiling
auf false zurückgesetzt. - Innerhalb von
Exit
der Parameter für die Squat-Animation auf false festgelegt. Dadurch wird die Squat-Animation deaktiviert. Dann wird die normale Collider-Höhe festgelegt, die vom character.NormalColliderHeight
zurückgegeben wird. character.NormalColliderHeight
. - In
HandleInput
Variable crouchHeld
den Eingabewert des Players fest. crouchHeld
in der crouchHeld
die Umschalttaste crouchHeld
, wird crouchHeld
auf true gesetzt. - In
PhysicsUpdate
Variablen belowCeiling
ein Wert zugewiesen, indem ein Punkt im Vector3
Format mit dem Kopf des Vector3
des Charakters an die CheckCollisionOverlap
Methode übergeben wird. Wenn es in der Nähe dieses Punktes zu einer Kollision kommt, bedeutet dies, dass sich der Charakter unter einer bestimmten Decke befindet. - Intern prüft
LogicUpdate
, ob crouchHeld
oder belowCeiling
wahr ist. Wenn keines davon wahr ist, ändert sich movementSM.CurrentState
in character.standing
.
Erstellen Sie das Projekt und klicken Sie auf
Abspielen . Jetzt können Sie sich in der Szene bewegen. Wenn Sie die
Umschalttaste drücken, setzt sich der Charakter hin und Sie können sich in der Hocke bewegen.
Sie können auch unter der Plattform klettern. Wenn Sie die
Umschalttaste unter den Plattformen loslassen, befindet sich der Charakter immer noch in der Hocke, bis er sein Obdach verlässt.
Steig auf!
Öffnen Sie
Jumping.cs . Sie sehen eine Methode namens
Jump
. Mach dir keine Sorgen darüber, wie es funktioniert; Es reicht zu verstehen, dass es verwendet wird, damit der Charakter unter Berücksichtigung von Physik und Animation springen kann.
Fügen Sie nun die üblichen
override
und speichern Sie das Skript
public override void Enter() { base.Enter(); SoundManager.Instance.PlaySound(SoundManager.Instance.jumpSounds); grounded = false; Jump(); } public override void LogicUpdate() { base.LogicUpdate(); if (grounded) { character.TriggerAnimation(landParam); SoundManager.Instance.PlaySound(SoundManager.Instance.landing); stateMachine.ChangeState(character.standing); } } public override void PhysicsUpdate() { base.PhysicsUpdate(); grounded = character.CheckCollisionOverlap(character.transform.position); }
- Innerhalb von
Enter
Singleton SoundManager
den Sound des Sprungs ab. Dann wird grounded
auf den Standardwert zurückgesetzt. Am Ende heißt Jump
. - In
PhysicsUpdate
Punkt neben den Beinen des Charakters an CheckCollisionOverlap
gesendet. Wenn sich der Charakter auf dem Boden befindet, wird grounded
auf True gesetzt. LogicUpdate
in LogicUpdate
grounded
True ist, rufen wir TriggerAnimation
auf, um die TriggerAnimation
zu aktivieren, ein Landegeräusch wird abgespielt und movementSM.CurrentState
ändert sich in character.standing
.
Damit haben wir die vollständige Implementierung der FSM-Verschiebung mithilfe
der Vorlage „State“ abgeschlossen . Erstellen Sie das Projekt, und führen Sie es aus. Drücken Sie die
Leertaste , um den Charakter zum Springen zu bringen.
Wohin als nächstes?
Die
Projektmaterialien haben einen Projektentwurf und ein fertiges Projekt.
Trotz ihrer Nützlichkeit weisen Zustandsmaschinen Einschränkungen auf. Concurrent State Machines und Pushdown-Automaten können einige dieser Einschränkungen umgehen. Sie können darüber im Buch von Robert Nystrom
Game Programming Patterns nachlesen.
Darüber hinaus kann das Thema vertieft werden, indem die
Verhaltensbäume untersucht werden, mit denen komplexere Objekte im Spiel erstellt werden.