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- rotationSpeedals 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:- paramParameter- paramanimation vom Typ Bool auf value.
- CheckCollisionOverlap: Er empfängt einen- Vector3und gibt ein- Vector3zurück, das bestimmt, ob sich innerhalb des angegebenen Radius vom- Vector3befinden.
- TriggerAnimation:- TriggerAnimationden Animationsparameter des Eingabeparameters- param.
- ApplyImpulse:- ApplyImpulseImpuls auf Character an, der dem Eingabeparameter- forceTyp- 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 StartCode eine Instanz der Zustandsmaschine und weist siemovementSM. Außerdem werden verschiedene Bewegungszustände instanziiert. Bei der Erstellung der einzelnen Bewegungszustände übergeben wir unter Verwendung desthissowie dermovementSMInstanz Verweise auf dieCharacterInstanz. Am Ende rufen wirInitializeformovementSMund übergebenStandingals Ausgangszustand.
- In der UpdateMethode rufen wirHandleInputundLogicUpdatefür denCurrentStatedermovementSMMaschine auf. EbensoFixedUpdatewir inFixedUpdatePhysicsUpdatefür denCurrentStatedermovementSMMaschine 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 basemit demselben Namen für jede überschriebene Methode auf. Dies ist eine wichtige Vorlage, die wir weiterhin verwenden werden.
- Die nächste Zeile, EntersetzthorizontalInputundverticalInputihre Standardwerte.
- Innerhalb von Exitrufen wir, wie oben erwähnt, dieResetMoveParamsMethode des- In der HandleInputMethode zwischenspeichern die VariablenhorizontalInputundverticalInputHandleInputWerte der horizontalen und vertikalen Eingabeachse. Dank dessen kann der Spieler den Charakter mit den Tasten W , A , S und D steuern .
- Bei PhysicsUpdatewirMoveund übergeben die VariablenhorizontalInputundverticalInputmultipliziert mit den entsprechenden Geschwindigkeiten. In der variablenspeeddie Bewegungsgeschwindigkeit und inrotationSpeeddie 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 Enterkonfigurieren wir die vonGroundedgeerbten Variablen. Wenden Sie dieMovementSpeedundRotationSpeedCharakters aufspeedundrotationSpeed. 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 voncrouchEingaben undjumpauf false zurückgesetzt.
- In HandleInputspeichern die VariablenHandleInputundjumpdie 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 Leertastejump.
- In LogicUpdateüberprüfen wir die VariablenLogicUpdateundjumpvom Typbool. Wenncrouchtrue ist, ändert sichmovementSM.CurrentStateincharacter.ducking. Wennjumptrue ist, ändert sich der Status incharacter.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 EnterParameter, der das Umschalten der Kniebeugenanimation bewirkt, auf "geduckt" gesetzt, wodurch die Kniebeugenanimation aktiviert wird. Den Eigenschaftencharacter.CrouchSpeedundcharacter.CrouchRotationSpeeddie Werte fürspeedundrotationzugewiesen, die die Bewegung und Winkelgeschwindigkeit des Zeichens beim Bewegen in einer Hocke zurückgeben .
 
 Nächstescharacter.CrouchColliderHeightlegt die Größe des Colliders des Zeichens fest, der beim Hocken die gewünschte Collider-Höhe zurückgibt. Am Ende wirdbelowCeilingauf false zurückgesetzt.
- Innerhalb von Exitder Parameter für die Squat-Animation auf false festgelegt. Dadurch wird die Squat-Animation deaktiviert. Dann wird die normale Collider-Höhe festgelegt, die vomcharacter.NormalColliderHeightzurückgegeben wird.character.NormalColliderHeight.
- In HandleInputVariablecrouchHeldden Eingabewert des Players fest.crouchHeldin dercrouchHelddie UmschalttastecrouchHeld, wirdcrouchHeldauf true gesetzt.
- In PhysicsUpdateVariablenbelowCeilingein Wert zugewiesen, indem ein Punkt imVector3Format mit dem Kopf desVector3des Charakters an dieCheckCollisionOverlapMethode ü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, obcrouchHeldoderbelowCeilingwahr ist. Wenn keines davon wahr ist, ändert sichmovementSM.CurrentStateincharacter.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 EnterSingletonSoundManagerden Sound des Sprungs ab. Dann wirdgroundedauf den Standardwert zurückgesetzt. Am Ende heißtJump.
- In PhysicsUpdatePunkt neben den Beinen des Charakters anCheckCollisionOverlapgesendet. Wenn sich der Charakter auf dem Boden befindet, wirdgroundedauf True gesetzt.
- LogicUpdatein- LogicUpdate- groundedTrue ist, rufen wir- TriggerAnimationauf, um die- TriggerAnimationzu 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.