Transitions
Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 30 of 50.
Who decides when the state changes? Asking the owner puts every rule back in one Update, as the switch did. The usual answer is that each state knows its own way out: in its Tick it checks its condition and asks the machine for the next state. This bomb waits until the player comes close, then burns its fuse, and goes back to waiting if the player runs:
public class Bomb : MonoBehaviour
{
public Transform player;
public StateMachine machine = new StateMachine();
public IState idle;
public IState fuse;
void Start()
{
idle = new IdleState(this);
fuse = new FuseState(this);
machine.ChangeState(idle);
}
void Update() { machine.Tick(); }
public bool PlayerNear()
{
return Vector3.Distance(transform.position, player.position) < 3f;
}
}
public class IdleState : IState
{
private Bomb bomb;
public IdleState(Bomb bomb) { this.bomb = bomb; }
public void Enter() { }
public void Exit() { }
public void Tick()
{
if (bomb.PlayerNear()) bomb.machine.ChangeState(bomb.fuse);
}
}
public class FuseState : IState
{
private Bomb bomb;
private float timer;
public FuseState(Bomb bomb) { this.bomb = bomb; }
public void Enter() { timer = 2f; }
public void Exit() { }
public void Tick()
{
if (!bomb.PlayerNear())
{
bomb.machine.ChangeState(bomb.idle);
return;
}
timer -= Time.deltaTime;
if (timer <= 0f)
{
Debug.Log("Boom!");
Object.Destroy(bomb.gameObject);
}
}
}Each state gets the bomb in its constructor and reaches the machine, the player test and the other states through it. The bomb makes every state once, in Start, so a state never makes another with new: two states that made each other in their constructors would loop until the stack overflows. The bomb's Update only ticks the machine, and the rules live in the states they belong to: the 2-second fuse is FuseState's business alone.
ChangeState runs FuseState's Exit and IdleState's Enter at once, but the rest of FuseState's Tick would still run after the call. The return stops it, otherwise the fuse would burn one more frame for a state that has already ended. Destroy is written Object.Destroy: a MonoBehaviour inherits it from Unity's Object class, and a plain class has to name the class.
Challenge
MediumA flytrap snaps at anyone who walks up to it. Flytrap.cs is ready: it makes the machine and the three states (the public fields open, snap and chew), starts Open and ticks the machine every frame, and PlayerInReach() says whether the player is closer than 2 across the ground. In FlytrapStates.cs every Enter is written (the colors, the timers, the Chomp! log). Write the transitions, in each state's Tick:
- Open: when the player is in reach, the trap snaps.
- Snap lasts 0.5 seconds. Then the trap chews if the player is still in reach, and opens again if they got away.
- Chew lasts 3 seconds, whoever is around, then the trap opens again.
The arrows walk the Player. Press Play, walk into the trap, then try to dodge it, then Check.
Try it yourself
using UnityEngine;
public class OpenState : IState
{
private Flytrap trap;
public OpenState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
trap.Paint(new Color(0.3f, 0.8f, 0.2f));
}
public void Tick()
{
// Snap when the player is in reach
}
public void Exit()
{
}
}
public class SnapState : IState
{
private Flytrap trap;
private float timer;
public SnapState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
timer = 0f;
trap.Paint(new Color(1f, 0.55f, 0.1f));
}
public void Tick()
{
// After 0.5 seconds: chew if the player is still in reach, open again if not
}
public void Exit()
{
}
}
public class ChewState : IState
{
private Flytrap trap;
private float timer;
public ChewState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
timer = 3f;
trap.Paint(new Color(0.5f, 0.05f, 0.1f));
Debug.Log("Chomp!");
}
public void Tick()
{
// After 3 seconds: open again
}
public void Exit()
{
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Game Architecture in Unity
1Components, Not Hierarchies
Small ComponentsA Base Enemy ScriptAbstract ComponentsComponents Working TogetherRecap: Modular Turret10Project: Arena Survivor
The HeroEnemy Types