A State Machine
Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 37 of 64.
The Beacon's SetState method would be the same in every object with states: a turret, an enemy, a door. That code can live in a class of its own, a state machine, which holds the current state and changes it. Each object makes one machine and calls it, instead of repeating the code:
public class StateMachine
{
public IState Current { get; private set; }
public void ChangeState(IState next)
{
Current?.Exit();
Current = next;
Current.Enter();
}
public void Tick()
{
Current?.Tick();
}
}
public class Beacon : MonoBehaviour
{
public Renderer lamp;
private StateMachine machine = new StateMachine();
private IState blink;
private IState steady;
void Start()
{
blink = new BlinkState(lamp);
steady = new SteadyState();
machine.ChangeState(steady);
}
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame) machine.ChangeState(machine.Current == steady ? blink : steady);
machine.Tick();
}
}The first ChangeState has no state to leave: Current is null, and ?. skips the call to Exit. Section 1 warned that ?. misses Unity's fake null; that is about destroyed Unity Objects, and the states are plain C# objects, so ?. is safe here. Current has a private set, so no script can swap the state without going through ChangeState and its Exit and Enter.
The order inside ChangeState matters whenever two states touch the same thing. Exit undoes what the old state changed, then Enter sets up the new one, so the new state has the last word. If a DarkState's Enter switched the lamp off and ran before BlinkState's Exit, that Exit would switch the lamp back on in the dark state. The StateMachine is a plain class too: the beacon, a turret and an enemy each make their own with new and call its Tick from their Update.
Challenge
MediumRun the player's ready states with a machine.
- In
StateMachine.cs, writepublic class StateMachinewithpublic IState Current { get; private set; }and aTick()that ticks it. ChangeState(IState next)ignores the current state; else Exit, setCurrent, Enter.Player: Start makesmachine,walk,sneakand walks; Update sneaks while Space is held, else walks, then ticks.
Press Play and hold Space: Sneak: enter. Then Check.
Try it yourself
// StateMachine: Current, ChangeState and Tick
All lessons in Game Architecture in Unity
1Components, Not Hierarchies
Small ComponentsA Base Enemy ScriptAbstract ComponentsComponents Working TogetherRecap: Modular TurretRecap: Twin Cannon4Serialized Data
Serializable ClassesLists in the InspectorEnums in the InspectorRecap: Loot TableRecap: Roll the Loot7State Machines
States as ClassesThe Alert StateA State MachineTransitionsEnemy BrainsThe Knight AttacksRecap: Door States2Interfaces in Unity
IDamageableInterfaces and TryGetComponentGetComponentsRecap: Interact KeyRecap: Nearest in ReachPractice on your own: Unity playground