Beyond If-Else Hell: Elegant State Machine pattern in Game Development
This post is an excerpt from the book Learning Game Architecture with Unity. Check my other books at Amazon. The State pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. This pattern is particularly useful when an object's behavior depends on its state and must change dynamically at runtime. Defining State State can be defined as the current condition of an object or system, i.e., the state decides the behaviour of an object or system. For example: Time of the day: Morning, Day, Afternoon, Evening, Night Current whether states: Sunny, Snowing, Raining Character physical states: Idle, Walking, Sleeping, Chasing, Hiding, Healthy, Hurt Defining state machine A state machine is a behavioral model that comprises a finite number of states, hence it is also referred to as a finite state machine (FSM). It operates based on the current state and a specified input, facilitating state transitions, and generating corresponding outputs. When an input is received, the state machine transitions from its current state to a new state based on predefined rules or transitions defined by the system's design. These transitions dictate how the system responds to different inputs or conditions. Let us take an example of a table lamp and break down its behaviour into a state machine: Another interesting example can be the state of an AI or NPC agent in a game scenario. The agent's behavior may change based on whether it can see the player. In such a situation, a state machine can manage the agent's states and transitions, allowing it to focus on specific behaviors within each state. Following are the states of the AI bot: Sleep: Initial state where the AI bot is not actively engaged in any action. Patrol: The AI bot is walking around the environment. Chase: The AI bot is actively chasing the player once they are in visible range. Hurt: The AI bot is being attacked by the player. Following are the state transitions of an AI bot: Sleep |→ Patrol: Transition to a walking state when the AI bot starts patrolling or moving around. Patrol |→ Chase: Transition to chasing state when the player becomes visible within the AI bot's range. Chase |→ Patrol: Transition to patrol state when the player goes out of sight of the AI Bot. By defining these key components for each state class, the overall behavior of the state machine can be clearly delineated, facilitating modular design and maintainability. Each state encapsulates its specific behavior, allowing for easier comprehension, modification, and extension of the system's functionality. Next, we will look at how we can implement a state machine for a given problem. We want to implement a state machine to control a character controller with various states such as attacking, defending, and returning home. Implementing state machine using inheritance The steps to be followed for implementing state machine using inheritance are as follows: Define a base state class. Create Separate classes for each concrete state, inheriting the base state class. State Machine will manage transition among different states. // Creating base state public abstract class CharacterState { public abstract void EnterState(CharacterController controller); public abstract void Update(CharacterController controller); public abstract void ExitState(CharacterController controller); } // Creating Concrete states inheriting Base State public class AttackingState : CharacterState { public override void EnterState(CharacterController controller) { // Enter Attacking state logic } public override void Update(CharacterController controller) { // Attacking state logic } public override void ExitState(CharacterController controller) { // Exit Attacking state logic } } Similarly, other states like ReturningHomeState can be implemented. Next, we will implement a CharacterController in which state transition logic will be implemented, as shown: // Character Controller class public class CharacterController { private CharacterState currentState; public void ChangeState(CharacterState newState) { if (currentState != null) { currentState.ExitState(this); } currentState = newState; currentState.EnterState(this); } public void Update() { if (currentState != null) { currentState.Update(this); } } } The CharacterController class manages the current state and transitions between states based on external events or conditions. This approach allows for flexible and modular design, making it easier to add, remove, or modify states as needed. Game design patterns and their usage are explained in the the context of game development with great details in the book:

This post is an excerpt from the book Learning Game Architecture with Unity. Check my other books at Amazon.
The State pattern is a behavioral design pattern that allows an object to alter its behavior when its internal state changes. This pattern is particularly useful when an object's behavior depends on its state and must change dynamically at runtime.
Defining State
State can be defined as the current condition of an object or system, i.e., the state decides the behaviour of an object or system. For example:
- Time of the day: Morning, Day, Afternoon, Evening, Night
- Current whether states: Sunny, Snowing, Raining
- Character physical states: Idle, Walking, Sleeping, Chasing, Hiding, Healthy, Hurt
Defining state machine
A state machine is a behavioral model that comprises a finite number of states, hence it is also referred to as a finite state machine (FSM). It operates based on the current state and a specified input, facilitating state transitions, and generating corresponding outputs.
When an input is received, the state machine transitions from its current state to a new state based on predefined rules or transitions defined by the system's design. These transitions dictate how the system responds to different inputs or conditions.
Let us take an example of a table lamp and break down its behaviour into a state machine:
Another interesting example can be the state of an AI or NPC agent in a game scenario. The agent's behavior may change based on whether it can see the player. In such a situation, a state machine can manage the agent's states and transitions, allowing it to focus on specific behaviors within each state.
Following are the states of the AI bot:
- Sleep: Initial state where the AI bot is not actively engaged in any action.
- Patrol: The AI bot is walking around the environment.
- Chase: The AI bot is actively chasing the player once they are in visible range.
- Hurt: The AI bot is being attacked by the player.
Following are the state transitions of an AI bot:
- Sleep |→ Patrol: Transition to a walking state when the AI bot starts patrolling or moving around.
- Patrol |→ Chase: Transition to chasing state when the player becomes visible within the AI bot's range.
- Chase |→ Patrol: Transition to patrol state when the player goes out of sight of the AI Bot.
By defining these key components for each state class, the overall behavior of the state machine can be clearly delineated, facilitating modular design and maintainability. Each state encapsulates its specific behavior, allowing for easier comprehension, modification, and extension of the system's functionality.
Next, we will look at how we can implement a state machine for a given problem. We want to implement a state machine to control a character controller with various states such as attacking, defending, and returning home.
Implementing state machine using inheritance
The steps to be followed for implementing state machine using inheritance are as follows:
- Define a base state class.
- Create Separate classes for each concrete state, inheriting the base state class.
- State Machine will manage transition among different states.
// Creating base state
public abstract class CharacterState
{
public abstract void EnterState(CharacterController controller);
public abstract void Update(CharacterController controller);
public abstract void ExitState(CharacterController controller);
}
// Creating Concrete states inheriting Base State
public class AttackingState : CharacterState
{
public override void EnterState(CharacterController controller)
{
// Enter Attacking state logic
}
public override void Update(CharacterController controller)
{
// Attacking state logic
}
public override void ExitState(CharacterController controller)
{
// Exit Attacking state logic
}
}
Similarly, other states like ReturningHomeState can be implemented. Next, we will implement a CharacterController in which state transition logic will be implemented, as shown:
// Character Controller class
public class CharacterController
{
private CharacterState currentState;
public void ChangeState(CharacterState newState)
{
if (currentState != null)
{
currentState.ExitState(this);
}
currentState = newState;
currentState.EnterState(this);
}
public void Update()
{
if (currentState != null)
{
currentState.Update(this);
}
}
}
The CharacterController class manages the current state and transitions between states based on external events or conditions. This approach allows for flexible and modular design, making it easier to add, remove, or modify states as needed.
Game design patterns and their usage are explained in the the context of game development with great details in the book: Learning Game Architecture with Unity, which is available @ Amazon, Amazon India, BPB International, BPB India.