DEV Community

Jussi Tuomi
Jussi Tuomi

Posted on

State machine controller for Unity

On my free time I love to create game prototypes using C# in Unity. One of these prototypes is a turn-based game where I need to have multiple game states and a fine control over them.

I started working on a typical finite state machine (FSM) for controlling the game scenario and player input in different game modes, such as battle and exploration.

First the state machine looked something like this:

StateMachine
StateExplorationUnitSelected
StateExplorationUnitMoving
StateBattleUnitSelected
StateBattleUnitMoving
StateBattleSelectingSkill
StateBattleCastingSkill

Immediately I started to stress about how bloated the single state machine would become as the codebase grows in size. This is when I divided it in two state machines:

ExplorationStateMachine BattleStateMachine
StateExplorationUnitSelected StateBattleUnitSelected
StateExplorationUnitMoving StateBattleUnitMoving
StateBattleSelectingSkill
StateBattleCastingSkill

After dividing the state machine in two, I wanted to have the ability to bundle related state machines together and allow their states to change the active state machine based on what happens in the game world. For example if player encounters an enemy in StateExplorationMoving - that state can call ChangeStateMachine(BattleStateMachine);

I created a parent state machine class that can hold a collection of child state machines:

PlayerStateMachine
ExplorationStateMachine
BattleStateMachine

In the above table PlayerStateMachine is a parent state machine for controlling child state machines. ExplorationStateMachine and BattleStateMachine can be considered as the states of the PlayerStateMachine.

After having this structure in place, I created a StateMachineController class that holds a list of parent state machines and runs their update methods.

StateMachineController.cs

I extracted the code from my prototype and started editing it to be more generic. You are free to use it for your own Unity projects if you want - and feel free to create a pull request if you have ideas to make it better. The project can be found from GitHub.

Top comments (2)

Collapse
 
nottesla profile image
NotTesla

Nice, I do a similar thing. Usually I put my states on a stack though, guess it depends on your use case. Any particular reason behind making those methods internal?

Collapse
 
jushii profile image
Jussi Tuomi

No special reason really. I made them internal instead of public out of force of habit of following coding conventions at my day job.