Tags: unity, fsm, state-machines, behavior-trees, ai, transitions, blackboard, game-dev Last updated: 2026-06-27

State Machines (FSM / Behavior Trees) Cheatsheet

Quick Reference

ApproachBest ForComplexity
Enum-based FSMSimple AI (patrol, chase, attack)Low
Class-based FSMMedium AI with state dataMedium
Animator FSMAnimation-driven behaviourLow
Behavior TreeComplex AI, modular decision-makingHigh

Enum-Based FSM

enum EnemyState { Idle, Patrol, Chase, Attack, Dead }
EnemyState currentState;

void Update() {
    switch (currentState) {
        case EnemyState.Idle:   IdleUpdate(); break;
        case EnemyState.Patrol: PatrolUpdate(); break;
        case EnemyState.Chase:  ChaseUpdate(); break;
        case EnemyState.Attack: AttackUpdate(); break;
        case EnemyState.Dead:   DeadUpdate(); break;
    }
}

void TransitionTo(EnemyState newState) {
    ExitState(currentState);
    currentState = newState;
    EnterState(newState);
}

void ExitState(EnemyState state) { /* cleanup */ }
void EnterState(EnemyState state) { /* setup */ }

State-Specific Logic

void IdleUpdate() {
    idleTimer -= Time.deltaTime;
    if (idleTimer <= 0) TransitionTo(EnemyState.Patrol);
    if (SeePlayer()) TransitionTo(EnemyState.Chase);
}

void ChaseUpdate() {
    MoveTowards(player.position);
    if (DistanceTo(player) < attackRange)
        TransitionTo(EnemyState.Attack);
    if (!SeePlayer())
        TransitionTo(EnemyState.Patrol);
}

Class-Based FSM

public abstract class State {
    public abstract void Enter();
    public abstract void Update();
    public abstract void Exit();
}

public class StateMachine : MonoBehaviour {
    State currentState;

    public void ChangeState(State newState) {
        currentState?.Exit();
        currentState = newState;
        currentState?.Enter();
    }

    void Update() => currentState?.Update();
}

Concrete States

public class PatrolState : State {
    Enemy owner;
    public PatrolState(Enemy e) => owner = e;

    public override void Enter() => owner.SetDestination(RandomWaypoint());
    public override void Update() {
        if (owner.ReachedDestination()) owner.SetDestination(RandomWaypoint());
        if (owner.SeesPlayer()) owner.machine.ChangeState(new ChaseState(owner));
    }
    public override void Exit() => owner.StopMoving();
}

Animator FSM (Unity Mecanim)

FeatureHow
StatesAnimation clips or Blend Trees
TransitionsArrow between states with conditions
ParametersFloat, Int, Bool, Trigger
LayersSeparate state machines (e.g. upper/lower body)
Sub-State MachinesNested FSMs for organisation
Blend TreesBlend between animations by parameter
Animator anim = GetComponent<Animator>();
anim.SetFloat("Speed", velocity.magnitude);
anim.SetBool("IsGrounded", isGrounded);
anim.SetTrigger("Jump");
anim.SetInteger("State", (int)currentState);

Animator Transition Conditions

TypeExample
Float (Greater/Less)Speed > 0.1
Bool (True/False)IsGrounded = true
TriggerJump (auto-resets)
Int (Equals/Greater/Less)Health <= 0
Exit TimeAfter 0.8 normalised time
Has Exit TimeTransition at exact frame

Behavior Trees

Core Nodes

NodeRole
Selector (OR)Try children left-to-right until one succeeds
Sequence (AND)Run children left-to-right until one fails
ConditionCheck a condition (succeed/fail)
ActionPerform an action (returns Running/Success/Fail)
DecoratorModify child behaviour (invert, repeat, cooldown)

Evaluation Flow

Selector
├── Sequence (Attack)
│   ├── Condition: EnemyInRange?
│   └── Action: Shoot()
└── Sequence (Patrol)
    ├── Action: MoveToWaypoint()
    └── Action: Wait(2s)

Simple BT Implementation

public enum NodeState { Running, Success, Failure }

public abstract class Node {
    public abstract NodeState Evaluate();
}

public class Selector : Node {
    List<Node> children;
    public override NodeState Evaluate() {
        foreach (var child in children) {
            var result = child.Evaluate();
            if (result != NodeState.Failure) return result;
        }
        return NodeState.Failure;
    }
}

public class Sequence : Node {
    List<Node> children;
    public override NodeState Evaluate() {
        foreach (var child in children) {
            var result = child.Evaluate();
            if (result != NodeState.Success) return result;
        }
        return NodeState.Success;
    }
}

Blackboard

Shared data store for AI decision-making.

VariableExample
targetTransform of current target
lastKnownPositionVector3 of last sighted player
alertLevelFloat 0–1
patrolIndexInt, current waypoint
public class Blackboard {
    Dictionary<string, object> data = new();

    public void Set<T>(string key, T value) => data[key] = value;
    public T Get<T>(string key) => (T)data[key];
    public bool Has(string key) => data.ContainsKey(key);
}

Choosing the Right Pattern

ScenarioUse
Simple enemy with 3–5 statesEnum FSM
Reusable state logic across enemiesClass-based FSM
Animation-heavy characterAnimator FSM
Complex decisions, many conditionsBehavior Tree
HybridBT for decision, FSM for execution
GOAP (Goal-Oriented Action Planning)Dynamic, emergent AI