This system was developed for the drone, but could be reused for other things. It works similarly to Unity's animator, which is a state machine for playing animations.
A FSM has a set of states, and is in one state at a time. There are transitions between states, and those only happen if their conditions are met. Each state can do things when entered, exited, and each frame. Example:
FSMs do things by raising game events. For example, there are game event scriptable objects like "DroneFSMEvent ScanningItem Enter", which is raised when the drone enters its ScanningItem state. The Game Event Scriptable Objects documentation describes how to use game events to do things.
If there isn't an event for entering, exiting, or each frame in a state, you can add it. Create a new GameEventScriptableObject
instance. Then, click on the scriptable object for the state, e.g. "DroneFSM State Idle", and assign the new game event to that state in the inspector.
A FSM is defined by scriptable objects for states, transitions, and parameters. To create one of those, right click in a folder -> Create -> Finite State Machine -> select one.
Each transition goes from one state to another, but only if a list of conditions are met. Those conditions use parameters, which are how to send data from other code into the FSM. Each parameter has a data type and an initial value. There are currently floats, bools, and triggers. Triggers are like bools, but they become false when used for a transition.
For example, the drone FSM has a transition from its Tutorial state to its Idle state, and that transition's only condition is a bool parameter called FinishedTutorial. Code sets that bool true when the player finishes the tutorial.
The FSM's scriptable objects are listed in a FSMDefinition
scriptable object, to consolidate everything for referencing in a scene. The FSMDefinition
is passed into the constructor of a FiniteStateMachineInstance
. Whereas FSMDefinition
has lists of states, transitions, and parameters, FiniteStateMachineInstance
represents the current state and current values of the parameters.
FiniteStateMachineInstance
has methods to set the values of parameters, as well as an Update()
method. Other code should set the values of parameters before calling FiniteStateMachineInstance.Update()
.
When the Update()
method gets called, it checks if any transitions meet their conditions. If so, the current state changes, and GameEventScriptableObject
s are raised for exiting the old state and entering the new one. It repeatedly checks for transitions until none happen. After checking transitions, a GameEventScriptableObject
is raised for the current state's update.