Chapter 06

AI Systems — Behavior Trees & Blackboard

State machines vs. Behavior Trees, Unreal's BT architecture, and how to frame the tradeoff in an interview context.

In this chapter

  1. State Machines vs. Behavior Trees
  2. Behavior Tree Architecture
  3. The Blackboard
  4. AIController & the Possession Model
  5. Environmental Query System (EQS)
1

State Machines vs. Behavior Trees

The interview question is "State machines vs. behavior trees — when and why?" The answer is not which is better — it is which fits the problem.

State Machines
  • Explicit, enumerated states
  • Predictable, authored transitions
  • Easy to reason about and debug
  • Best for small, fixed behavior sets
  • Designers can author beats precisely
Behavior Trees
  • Composable, reusable task nodes
  • Priority-based, reactive selection
  • Scales to complex layered behaviors
  • Best for open-ended, reactive AI
  • Easier to add new behaviors without breaking old ones

The answer framed around designers

The real deciding factor is often who needs to author it and what they need to control:

In practice, ship titles use both. A boss uses a state machine for its phase transitions (authored, scripted), and a behavior tree for what it does within each phase (reactive, composable).

2

Behavior Tree Architecture

Unreal's Behavior Tree system evaluates a tree of nodes top-to-bottom, left-to-right each tick, selecting the highest-priority branch whose conditions are satisfied.

Node types

Node typeRoleExample
CompositeControls flow between childrenSelector, Sequence, Simple Parallel
TaskA leaf node that does workMoveTo, Wait, PlayAnimation, Attack
DecoratorA condition on any node — gates or abortsBlackboard check, Cooldown, Is In Range
ServiceRuns on a tick interval while its branch is activeUpdate nearest enemy, refresh EQS query

Composites in detail

Selector
  • Tries children left to right
  • Succeeds on the first child that succeeds
  • Fails only if all children fail
  • Used for fallback priority: try attack, else retreat, else idle
Sequence
  • Runs children left to right
  • Succeeds only if all children succeed
  • Aborts on first child failure
  • Used for ordered steps: move to target, then attack

A simple combat BT

Root
└── Selector
    ├── Sequence  [HasTarget?]          ← Decorator gate
    │   ├── Service: UpdateTargetLocation
    │   ├── MoveTo(TargetLocation)
    │   └── Task: MeleeAttack
    ├── Sequence  [HeardSound?]
    │   ├── MoveTo(SoundLocation)
    │   └── Task: Investigate
    └── Task: Patrol

Abort types on decorators

When a decorator condition changes mid-execution, abort types control what happens:

Abort typeBehavior
NoneNo abort — condition is only checked when the node is first entered
SelfAborts the subtree this decorator is on if the condition becomes false
Lower PriorityAborts any lower-priority branch if this condition becomes true
BothAborts self if condition goes false; aborts lower priority if it goes true
Incorrect abort types are one of the most common Behavior Tree bugs. An AI that ignores a new threat because it is mid-patrol is usually a missing "Lower Priority" abort on the combat condition.

Writing custom Tasks and Decorators

// Custom task — subclass UBTTask_BlueprintBase in BP,
// or UBTTaskNode in C++
UCLASS()
class UBTTask_MeleeAttack : public UBTTaskNode
{
    GENERATED_BODY()

    virtual EBTNodeResult::Type ExecuteTask(
        UBehaviorTreeComponent& OwnerComp,
        uint8* NodeMemory) override;
};

3

The Blackboard

The Blackboard is the AI's shared memory — a key-value store that the Behavior Tree reads and writes through decorators, services, and tasks. It decouples the AI's data from its logic.

Common Blackboard keys

KeyTypeUsed by
TargetActorObject (AActor)MoveTo, MeleeAttack, decorators
TargetLocationVectorMoveTo patrol waypoints
LastKnownPlayerLocVectorInvestigation behavior
bIsAlertBoolDecorator gates for combat vs idle
CurrentHealthFloatRetreat threshold decorators

Writing to the Blackboard

// From C++ (e.g. in a Service or AIController)
UBlackboardComponent* BB = OwnerComp.GetBlackboardComponent();
BB->SetValueAsObject(TEXT("TargetActor"), PerceivedActor);
BB->SetValueAsVector(TEXT("TargetLocation"), TargetActor->GetActorLocation());
The Blackboard is intentionally simple — no methods, no logic. It is a data bus. The Behavior Tree reads it; AI controllers and perception systems write it. Keep this separation clean or your AI becomes hard to debug.

4

AIController & the Possession Model

The AAIController is the bridge between the Behavior Tree and the Pawn. It possesses an AI Pawn, runs the BT, owns the Blackboard, and owns the AI Perception component.

UCLASS()
class AEnemyAIController : public AAIController
{
    GENERATED_BODY()

protected:
    UPROPERTY(EditDefaultsOnly)
    UBehaviorTree* BehaviorTree;

    virtual void OnPossess(APawn* InPawn) override
    {
        Super::OnPossess(InPawn);
        RunBehaviorTree(BehaviorTree);
    }
};

AI Perception

The UAIPerceptionComponent handles sight and hearing — it fires delegates when the AI sees or hears something, and the AIController updates the Blackboard in response.

// Bind to perception events in AIController
PerceptionComponent->OnTargetPerceptionUpdated.AddDynamic(
    this, &AEnemyAIController::OnPerceptionUpdated
);

void AEnemyAIController::OnPerceptionUpdated(
    AActor* Actor, FAIStimulus Stimulus)
{
    if (Stimulus.WasSuccessfullySensed())
    {
        GetBlackboardComponent()->SetValueAsObject(
            TEXT("TargetActor"), Actor);
    }
}

5

Environmental Query System (EQS)

EQS lets AI ask spatial questions of the world — "What is the best cover position?", "Where can I flank the player?", "Which patrol point is closest and not visible to the player?" — and get back a scored set of candidates.

How it works

  1. Generator — produces candidate points (grid around actor, patrol points, actors of a class)
  2. Tests — score and filter candidates (distance, line of sight, dot product to target)
  3. Result — the best scoring candidate is stored in the Blackboard and used by the BT

Running EQS from a BT Service

The most common pattern: a BT Service runs an EQS query on a timer and writes the best result to the Blackboard. The Behavior Tree then uses that location for movement tasks — no per-frame spatial logic in C++ required.

EQS is primarily a designer tool — queries are built as assets in the editor. Engineers define custom generators and tests in C++ when needed, but most queries are authored entirely without code.
← Chapter 5 ↑ Index Chapter 7 →