# Finite State Machine ## Pattern Scope I don’t separate state machines from the **State** pattern, and neither do most **AI behavior systems**. _Unity_, for example, uses **behavior trees** for animations, a very similar concept, almost the same pattern with a different name. The idea is to **encapsulate behaviors into States**. These States have a controller that manages transitions between them, ensuring a **continuous and more complex behavior** of the entity as a whole. As you may notice, **States can be easily swapped** if the correct abstraction is used. **Interfaces are your friends** for this, and a _finite state machine_, as the name indicates, is designed to have a **finite combination of states**. For example, let’s say we have a state machine with a `Seek` state defined, and we’ve created variations of this state. Now, the same enemy (with the same visuals and without any extra implementations) can exhibit **behavior variations**. _Doom (2016)_, for example, features basic enemies that vary slightly in their behaviors, this adds flavor to the gameplay. Although [Game Programming Patterns by Robert Nystrom](https://gameprogrammingpatterns.com/singleton.html) covers this pattern, I first learned about it through the [Infallible Code YouTube channel](https://youtu.be/5PTd0WdKB-4?si=deivaWSyS6ZwX6Ey), which I used as a guideline for my first pattern implementations. That said, I prefer using **interface segregation**[^1] over inheritance, which is the Infallible Code approach. ### <img src="00-assets/01-images/02-icons/code-icon-36x36.png" align="left" width="24px" height ="24px" style="margin:2px" /> Pattern Application Let’s keep it simple and near the basics. A first step is the definition of the **interface**: ```csharp public interface IState { void Start(); IEnumerator Run(); void Stop(); } ``` > [!IMPORTANT] > As you may notice, the `Run()` method returns an `IEnumerator`, which is commonly used inside Unity to simulate **multi-threaded-like** executions through coroutines. > States may be interrupted, so their current running behavior can be broken to let other states enter. > However, `Start()` and `Stop()` should be **linear executions** to ensure data consistency and synchronization with any async operations. Now, we can define a **State Machine interface** that delegates entity behavior to its states: ```csharp public interface IStateMachine { IState[] States { get; } IState CurrentState { get; } void SetState(IState newState); } ``` After that, it’s time for the **finite** part: ```csharp public class EnemyStateMachine : IStateMachine { private readonly IState[] states; #region IStateMachine_Values public IState[] States { get => this.states; } public IState CurrentState { get; private set; } #endregion public EnemyStateMachine(IState[] states) { #if DEFENSIVE_ENABLE //A check to ensure correct configurations could be here #endif this.states = states; } #region IStateMachine_Methods public void SetState(IState newState) { #if DEFENSIVE_ENABLE //Check if the given state is valid #endif this.CurrentState.Stop(); this.CurrentState = newState; this.CurrentState.Start(); } #enregion } public enum EnemyStates { Idle = 0, Patrol = 1, Follow = 2 } ``` The **state flow** can be managed linearly (one state calling another), by input responses, or with both approaches, something like `Idle → Patrol → Idle`, and repeat. However, if the player enters the field of view of a hypothetical enemy during patrol, that **_input may abruptly change_** the current state. A more **OOP-style** approach, responsive to events, could look like this: ```csharp public class Enemy : MonoBehaviour { private EnemyStateMachine stateMachine; public IState[] BehaviourStates => this.stateMachine.States; private void Awake() { this.stateMachine = new EnemyStateMachine ( new IState[] { new BaseEnemyIdle(this.stateMachine), new BaseEnemyPatrol(this.stateMachine), new BaseEnemyFollow(this.stateMachine) } ); } public void OnEnterFieldOfView(Entity entity) { if(entity is Player) this.stateMachine .SetState((int)this.BehaviourStates[EnemyStates.Follow]); } } ``` If we are using a **DOP**[^2] (Data-Oriented Programming) approach, `IStateMachine` could be divided into something like `IFlagsStateMachine`. For example, keeping properties in the data structure, and letting the **system**[^3] be the state machine that manages all states based on **inputs** and **internal information** of each entity. > [!NOTE] > As a matter of fact, I prefer an **ECS** (Entity Component System) approach, where the system manages information inside a well-structured loop. > However, that setup makes this pattern harder to represent for this article. ### <img src="100-assets/01-images/02-icons/info-icon-36x36.png" align="left" width="24px" height ="24px" style="margin:2px" /> Considerations > [!IMPORTANT] > The graphics need to be updated and managed according to the **current state**. > We can do this directly inside the `Run()` call, but Unity, for example, has a specific system for animations, so it’s important to **synchronize executions** to avoid visual glitches. > [!WARNING] This pattern works **_very well with [[00-bytecode]]_**, which is **_not described or used here_** to avoid **_overextending the article’s scope_**. However, **_if you want to dive deeper into state management and complex behaviors_**, check it out. # References - [Game Programming Patterns by Robert Nystrom](https://gameprogrammingpatterns.com/singleton.html) - [Infallible Code Youtube channel](https://youtu.be/5PTd0WdKB-4?si=deivaWSyS6ZwX6Ey) [^1]: [[00-solid]] [^2]: [[01-programming_paradigms]] [^3]: [[03-ecs_architecture]]