State Pattern Using Unity
Learn all about the Finite State Machine design pattern in Unity. Then implement it to control the movement of your own character! By Najmm Shora.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
State Pattern Using Unity
20 mins
Defining State and State Machine
Navigate to RW/Scripts and open StateMachine.cs.
The State Machine will provide an abstraction for, you guessed it, a state machine. Notice the CurrentState property inside this class. This will store the reference to the current active state of the state machine.
Now to define the idea of a state, go to RW/Scripts and open State.cs in your IDE.
State is an abstract class you’ll use as a blueprint to derive from, for all the state classes in this project. Some code has already been provided for you.
DisplayOnUI only displays the name of the current state on the screen UI. You don’t need to worry about its inner workings but you do need to understand it takes an enumerator of type UIManager.Alignment as an input parameter which can either be Left or Right. This results in the name of the state displaying on either the bottom left or bottom right of the screen respectively.
Additionally, there are two protected variables, character and stateMachine. The character references an instance of the Character class while stateMachine references an instance of the State Machine that associates with the state.
The constructor links the character and stateMachine when a state instance is created.
Multiple instances of Character in the scene can each have their own set of states and state machines.
Now, add the following methods inside of State.cs and save the file:
public virtual void Enter()
{
DisplayOnUI(UIManager.Alignment.Left);
}
public virtual void HandleInput()
{
}
public virtual void LogicUpdate()
{
}
public virtual void PhysicsUpdate()
{
}
public virtual void Exit()
{
}
These virtual methods define the key points of a state discussed earlier. When the State Machine transitions between states, you call Exit on the previous state and Enter for the new active state.
The HandleInput, LogicUpdate and PhysicsUpdate together define the update loop. HandleInput handles the input. LogicUpdate handles the core logic and the PhyiscsUpdate handles the physics logic and calculations.
Now open StateMachine.cs once again, add the following methods and save the file:
public void Initialize(State startingState)
{
CurrentState = startingState;
startingState.Enter();
}
public void ChangeState(State newState)
{
CurrentState.Exit();
CurrentState = newState;
newState.Enter();
}
Initialize configures the state machine by setting CurrentState to the startingState variable and calling Enter on it. This initializes the state machine by setting the active state for the first time.
ChangeState handles transitions between States. It calls Exit on the old CurrentState before updating its reference to newState. Finally it calls Enter on the newState.
With that, you’ve defined a State and a State Machine.
Creating the Movement States
Take a look at the following state diagram which shows the various movement states of an in-game player entity. In this section, you’ll implement the state pattern for the shown movement FSM:

Take note of the various movement states, namely Standing, Ducking, and Jumping, and how the input can cause a state transition. This is a hierarchical FSM where Grounded is the super-state for the Ducking and Standing sub-states.
Go back to Unity and navigate to RW/Scripts/States. You’ll find several C# files with names ending in State.
Each of these files defines one single class, all of which inherit from State. As such, these classes define the states you’ll use in this project.
Now open the Character.cs from RW/Scripts.
Navigate to the top of the #region Variables of the file and add the following code:
public StateMachine movementSM;
public StandingState standing;
public DuckingState ducking;
public JumpingState jumping;
This movementSM references the state machine that handles movement logic for the Character instance. You also added references for three states you’ll implement for each type of movement.
Navigate to #region MonoBehaviour Callbacks in the same file. Add the following MonoBehaviour methods and then save:
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
Start, the code creates an instance of State Machine and assigns it tomovementSMas well as creating the instances of the various movement states. As you create each of the movement states, you pass references to theCharacterinstance using thethiskeyword as well asmovementSMinstance. Finally, you callInitializeonmovementSMand pass inStandingas the starting state. - In the
Updatemethod, you callHandleInputandLogicUpdateon theCurrentStateofmovementSM. Similarly, inFixedUpdate, you callPhysicsUpdateon theCurrentStateofmovementSM. This essentially delegates the tasks to the active state, which is what the State pattern is all about.
Now you need to define the behavior inside each of the movement states. Brace yourself for lots of code!
Two Feet Firmly on the Ground
Go back to RW/Scripts/States in the Project window.
Open Grounded.cs and note that this class has a constructor that matches that of the State. This makes sense since this class is inhering from it. You’ll see the same in all the other state classes as well.
Add the following code:
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);
}
Here’s what is happening:
- You override some of the virtual methods defined in the parent class. In order to keep any functionality that could exist in the parent you call the
basemethod of the same name from within each overridden method. This is an important pattern you’ll continue to use. - In the next line of
Enter, thehorizontalInputandverticalInputvariables are set to their default values. - Inside
Exit, you callResetMoveParamsmethod ofcharacterfor clean-up while transitioning to another state, as described before. - In
HandleInputmethod,horizontalInputandverticalInputcache the horizontal and vertical input axis values. As such, you can use the W, A, S and D keyboard keys to move the character. - In the
PhysicsUpdate, you make a call toMoveby passing in thehorizontalInputandverticalInputvariables multiplied by the respective speeds. Thespeedvariable stores the translation speed whereasrotationSpeedstores the angular speed.
Now open Standing.cs and note that it inherits from Grounded. This is because Standing is a sub-state for Grounded, as discussed previously. There are various ways of implementing this relationship but in this tutorial you’ll use inheritance.
Add the following override methods and save the script:
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);
}
}
Also, the variables for storing input, crouch and jump, are reset to false.
- In
Enteryou configure some variables inherited fromGrounded. You apply the Character’sMovementSpeedandRotationSpeedto thespeedandrotationSpeed. They apply to the normal translation and angular speeds intended for the character entity respectively.Also, the variables for storing input,
crouchandjump, are reset to false. - Inside
HandleInput,crouchandjumpstore the user input for crouching and jumping respectively. In the Main scene, if the user presses the Shift key, crouch is set to true. Similarly, the user can use the Space key forjump. - In
LogicUpdateyou check theboolvariablescrouchandjump. Ifcrouchis true,movementSM.CurrentStatechanges tocharacter.ducking. Otherwise, ifjumpis true, it changes tocharacter.jumping.
Save and build the project and click Play. You should be able to move around using the W, A, S and D keys. If you try pressing the Shift or Space keys right now, unexpected behavior will occur since the corresponding states aren’t implemented yet.

Try moving under the bench shaped platforms. You’ll notice that isn’t possible due to the Character’s collider height. To let the Character do this, you’ll add the ducking behavior.