State Machine¶
A State Machine is a commonly used pattern that allows to isolated the complexity of multiple tasks in different nodes, in a way that each node is not aware of what others do.
About State Machines
For a full description of what a finite state machine is check this Wikipedia article.
Creating States¶
Let's start seeing how to create states before creating a state machine. A State is a single node unit from the state machine. To create one, create a class that inherits from the StateMachine.State
abstract class:
public class MyState1 : StateMachine.State
{ }
A State has 3 virtual methods that can be overriden in order to execute its custom logic:
// Executed when the machine changes to this state
void WhenEnter(StateMachine machine)
{ }
// Executed when the machine exists from this state
protected virtual void WhenExit(StateMachine machine)
{ }
// Executed every frame while this state is active
protected virtual void WhenUpdate(StateMachine machine)
{ }
A state has an IsActive
property that can be queried to check if this state is currently the active one.
If you need to hook events to a State in order to make it work with other scripts, you can also subscribe to its event system.
// Executed when the machine changes to this state
event Action<StateMachine, State> EventOnEnter;
// Executed when the machine exists from this state
event Action<StateMachine, State> EventOnExit;
// Executed every frame while this state is active, before the WhenUpdate(...)
event Action<StateMachine, State> EventOnBeforeUpdate;
For example, let's first create an instance of MyState1
:
MyState1 state1 = new MyState();
Now let's hook an external method that prints a message when the state is entered:
state1.EventOnEnter += this.OnEnterState;
The OnEnterState(...)
method must have the following signature:
public void OnEnterState(StateMachine machine, State state)
{
Debug.Log("Hello World!");
}
Creating a State Machine¶
To create a state machine, create a class that inherits from StateMachine
:
public class MyStateMachine : StateMachine
{
public MyStateMachine(State state) : base(state)
{ }
}
First State
Note that a State Machine requires at least one state to be passed to the constructor. This is the first starting state that the machine will begin with.
The developer is responsible for calling its Update()
method. We recommend calling it in a MonoBehaviour's Update()
.
To instruct the machine to change from one state to another, use the Change(State)
method:
MyState1 state1 = new MyState1();
MyState2 state2 = new MyState2();
// Initialize with state1
MyStateMachine machine = new MyStateMachine(state1);
// Change to state2
machine.Change(state2);
A State Machine also has 2 events that allow methods to be subscribed, which are launched as soon as there is a change in the currently active state:
event Action<State> EventStateEnter;
event Action<State> EventStateExit;