Behavior Trees for Game AI

Updated June 2026
Behavior trees are the industry-standard architecture for complex NPC decision-making in games. They organize AI logic into a modular hierarchy of tasks and conditions that is evaluated top-down each tick, making it possible to build, reuse, and extend sophisticated enemy behaviors without the transition explosion that plagues large finite state machines.

Behavior trees gained widespread adoption after Halo 2 demonstrated their effectiveness for managing combat AI that needed to handle dozens of possible actions depending on the tactical situation. Since then, every major game engine has adopted them. Unreal Engine ships a full behavior tree editor with visual debugging. Unity supports them through packages like NodeCanvas and Behavior Designer. Godot has community plugins that provide similar functionality. The architecture scales from simple enemies with a handful of behaviors to complex squad leaders coordinating group tactics.

Step 1: Understand Node Types

Every behavior tree is built from four categories of nodes. Mastering these four types is the foundation for everything else.

Composite nodes control execution flow and have multiple children. The two essential composites are Sequence and Selector. A Sequence runs its children left to right and succeeds only if every child succeeds, failing immediately if any child fails. Think of it as an AND operation. A Selector runs its children left to right and succeeds as soon as any child succeeds, failing only if every child fails. Think of it as an OR operation. A Sequence answers "can I do all of these things?" while a Selector answers "can I do any of these things?"

Decorator nodes wrap a single child and modify its behavior or result. An Inverter flips Success to Failure and vice versa. A Repeater runs its child multiple times or indefinitely. A Cooldown prevents its child from executing again within a time window. A ForceSuccess always returns Success regardless of what the child returns. Decorators are how you add nuance to the tree without complicating the core logic.

Leaf action nodes are the actual behaviors: MoveTo, Attack, PlayAnimation, SetBlackboardValue, Wait. These are the things the NPC physically does in the game world. Each action returns Success when it completes, Failure if it cannot be performed, or Running if it is still in progress and needs more ticks to finish.

Leaf condition nodes check the state of the world: IsPlayerVisible, IsHealthBelow, HasAmmo, IsAllyNearby. Conditions return Success if the condition is true and Failure if it is false. They never return Running because a condition check is instantaneous. Conditions are typically placed before actions in a Sequence, acting as gates that prevent the action from executing unless the preconditions are met.

Step 2: Design Your Tree Structure

The top level of a behavior tree is almost always a Selector, because the NPC needs to pick one behavior from several options. Each child of the root Selector represents a major behavior domain, arranged by priority from left to right. The tree evaluates left to right, so the leftmost branch that succeeds determines what the NPC does.

A typical enemy tree structure follows this priority order:

Survival (highest priority): If health is critically low and an escape route exists, flee. This branch uses a Sequence: check IsHealthCritical, check HasEscapeRoute, then execute FleeToSafety. Because it is the leftmost child of the root Selector, it always gets evaluated first. If the NPC is dying, nothing else matters.

Combat: If a threat is present, engage it. This branch is itself a Selector containing sub-branches for different combat tactics: take cover and shoot, throw grenades, melee attack, reposition. Each tactic is a Sequence of conditions and actions. The Selector tries each tactic in priority order and uses the first one whose conditions pass.

Investigation: If something suspicious was detected but no confirmed threat exists, investigate. Move to the disturbance location, look around, search nearby areas. This gives the NPC a believable response to partial information rather than either ignoring it or instantly entering full combat mode.

Patrol (lowest priority): If nothing else is happening, follow the patrol route. This is the fallback behavior that keeps the NPC busy when all higher-priority branches fail their conditions.

Sketch this tree on paper before writing any code. Visual layout reveals structural issues that are hard to see in code, like missing fallback behaviors or unreachable branches.

Step 3: Implement the Blackboard

The blackboard is a shared key-value store that behavior tree nodes use to read and write runtime data. Instead of passing parameters between nodes directly, everything goes through the blackboard. This decoupling is what makes behavior tree nodes reusable.

Common blackboard keys for an enemy NPC include TargetActor (reference to the current threat), LastKnownPosition (vector3 of where the target was last seen), ThreatLevel (numeric score combining distance, visibility, and ally status), CurrentHealth (for condition checks), HomePosition (where to return after investigation), and PatrolIndex (which waypoint the NPC is heading toward).

Any system can write to the blackboard, not just the behavior tree. A perception system might update TargetActor and LastKnownPosition whenever a new sighting occurs. A damage system might update CurrentHealth. A squad coordinator might write a TacticalOrder that the behavior tree reads to determine whether to flank left or right. This separation of data producers and data consumers is one of the behavior tree architecture's biggest practical advantages.

Keep blackboard keys well-documented and typed. A common bug is two nodes writing to the same key with different semantics, silently corrupting the data. Use a centralized key definition file or enum so every reference to a blackboard key is explicit and searchable.

Step 4: Build Leaf Nodes

Leaf nodes are where abstract decision-making meets concrete game systems. Each leaf node wraps a single operation and must cleanly return one of three statuses every tick.

Success means the operation completed. A MoveTo node returns Success when the NPC reaches its destination. An Attack node returns Success when the attack animation finishes and damage is applied.

Failure means the operation cannot proceed. MoveTo returns Failure if no valid path exists. Attack returns Failure if the target is out of range or the weapon has no ammo.

Running means the operation is still in progress. MoveTo returns Running on every tick while the NPC is still walking toward the target. Running is what allows behavior trees to handle multi-frame actions naturally.

Build leaf nodes as narrow, focused units. A "MoveTo" node should only handle movement. Do not combine movement with attack logic or animation triggers. The narrower each node's responsibility, the more easily you can recombine them into different behavior patterns. A MoveTo node used in a patrol Sequence works identically when reused in a flee Sequence or an investigate Sequence because it only cares about getting the NPC to a destination.

Step 5: Compose and Test Subtrees

Build your behavior tree bottom-up by composing small, tested subtrees into larger structures. Start with a simple patrol subtree: a Sequence of GetNextWaypoint, MoveTo, Wait. Test it in isolation until the NPC patrols correctly. Then build a combat subtree: a Selector of attack tactics, each a Sequence of conditions and actions. Test it in isolation with a manually spawned threat.

Once each subtree works independently, connect them under the root Selector with appropriate conditions gating each branch. Test the full tree by running scenarios that exercise different priority levels: patrol with no threats, spotting the player, losing the player, taking damage, low health retreat. Each scenario should activate the correct branch and transition cleanly when conditions change.

Create test utilities that let you force specific blackboard states. Being able to set IsHealthCritical to true from a debug console and immediately see the flee branch activate is invaluable for verifying that the tree structure is correct without having to recreate complex game scenarios every time.

Step 6: Handle Running States and Interrupts

The Running state is where behavior trees diverge most from other architectures and where most implementation bugs hide. When a node returns Running, the tree must remember where it left off and resume from that node on the next tick rather than starting from the root. This "resumption" behavior is critical for multi-frame actions like pathfinding or attack animations.

The challenge comes when a higher-priority branch becomes valid while a lower-priority action is Running. Suppose the NPC is in the middle of a patrol MoveTo (Running) and suddenly the perception system detects the player. The combat branch is higher priority than patrol, so the tree should abandon the patrol and switch to combat. This requires an abort mechanism.

Unreal Engine handles this with Abort Type settings on decorator nodes. A "Lower Priority" abort means the decorator monitors its condition even while lower-priority branches are executing, and if the condition becomes true, it aborts the currently running branch and redirects execution to its own branch. A "Self" abort means the decorator monitors its condition while its own branch is running and aborts if the condition becomes false.

Without proper abort handling, NPCs will finish their current action before responding to new stimuli, which makes them feel sluggish and unresponsive. With abort handling, NPCs can drop what they are doing and immediately react to threats, which makes them feel alert and dangerous.

Behavior Trees vs Finite State Machines

The choice between behavior trees and FSMs is not always clear-cut. FSMs are simpler to implement and debug for NPCs with fewer than eight states. Behavior trees scale better because adding a new behavior means adding a new branch without modifying existing branches, whereas adding a new state to an FSM requires defining transitions to and from every connected state.

Many production games use both. A high-level FSM might manage macro states (combat, exploration, social) while behavior trees manage the detailed behaviors within each macro state. This hybrid approach gets the clarity of FSMs at the strategic level and the flexibility of behavior trees at the tactical level.

Key Takeaway

Behavior trees succeed because they separate what the NPC should do (the tree structure) from how it does it (the leaf nodes) and from what it knows (the blackboard). This separation makes every piece independently testable, reusable, and replaceable.