The following boilerplate code is for a basic finite state machine implementation in Unity, written for my own reuse with comments provided on usage. It was inspired by the code and concepts from Unity Technologies’ Finite State Machines course on Unity Learn. I highly recommend checking out it and their other free videos for more information on the basics.
SampleStateMachine.cs
SampleStateMachine.cs is the necessary code that needs to be added to the object whose state you need to manage. This could be your player, game manager or any other gameobject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SampleStateMachine : MonoBehaviour
{
// Defines the object's states. Replace ObjectStateBase with the base state and the other two (or more) states with your other states.
private ObjectStateBase currentState;
public readonly ObjectStateOne OneState = new ObjectStateOne();
public readonly ObjectStateTwo TwoState = new ObjectStateTwo();
// Transitions between states. Replace ObjectStateBase with the base state.
public void TransitionToState (ObjectStateBase state) {
// Runs the current state's exit state code. Try-catch is needed because on instantiation there is no current state to run ExitState on.
try {
currentState.ExitState(this);
} catch {
Debug.Log("No current state.");
}
// Changes the current state to the state passed to the method.
currentState = state;
// Runs the current state's enter state code.
currentState.EnterState(this);
}
// Transitions to the initial state on instantiation. Replace OneState with the initial state of your choosing.
void Start()
{
TransitionToState(OneState);
}
// Runs the current state's update code.
void Update()
{
currentState.Update(this);
}
// Runs the current state's update code.
void FixedUpdate()
{
currentState.FixedUpdate(this);
}
}
ObjectStateBase.cs
ObjectStateBase.cs is the boilerplate for your object’s base state class, which will be inherited by the object’s states. It defines the methods to be use in your other states states. If there’s any method that every state is going to need, you can define it here and call it wherever you need. A few common methods are defined, but are not strictly required for your state machine.
using UnityEngine;
public abstract class ObjectStateBase
{
// Defines all the methods used by states for this object. In this case, EnterState, Update (monobehavior), FixedUpdate (monobehavior), ExitState.
public abstract void EnterState(SampleStateMachine machine);
public abstract void Update(SampleStateMachine machine);
public abstract void FixedUpdate(SampleStateMachine machine);
public abstract void ExitState(SampleStateMachine machine);
}
ObjectStateOne.cs
This is a boilerplate implementation of an arbitrary state, with the required methods implemented and an example of how to switch between states.
using UnityEngine;
public class ObjectStateOne : ObjectStateBase
{
public override void EnterState(SampleStateMachine machine)
{
Debug.Log("Runs this code when State One is entered.");
}
public override void FixedUpdate(SampleStateMachine machine)
{
Debug.Log("Runs this code on FixedUpdate when State One is the current state.");
}
public override void Update(SampleStateMachine machine)
{
Debug.Log("Runs this code on Update when State One is the current state.");
// Transitions to state two on keypress.
if (Input.GetKeyUp("2")) {
machine.TransitionToState(machine.TwoState);
}
}
public override void ExitState(SampleStateMachine machine)
{
Debug.Log("Runs this code when State One is exited.");
}
}
ObjectStateTwo.cs
Another sample state, because a state machine requires at least two states. Although the code is near-identical for this example, most states have vastly different code, which is why state machines are useful.
using UnityEngine;
public class ObjectStateTwo : ObjectStateBase
{
public override void EnterState(SampleStateMachine machine)
{
Debug.Log("Runs this code when State Two is entered.");
}
public override void FixedUpdate(SampleStateMachine machine)
{
Debug.Log("Runs this code on FixedUpdate when State Two is the current state.");
}
public override void Update(SampleStateMachine machine)
{
Debug.Log("Runs this code on Update when State Two is the current state.");
// Transitions to state one on keypress.
if (Input.GetKeyUp("1")) {
machine.TransitionToState(machine.OneState);
}
}
public override void ExitState(SampleStateMachine machine)
{
Debug.Log("Runs this code when State Two is exited.");
}
}
If you put the Sample State Machine on any object in your scene and check the Console, you will see that it is working (though spamming the Console with a log on every Update and FixedUpdate). If you press “1” or “2” on your keyboard, you will see the Console messages change accordingly.