Behavior Tree Blackboards

A behavior tree is very good at describing control flow — what to try first, what to fall back to — and completely silent about data flow. The tree says “Chase the player,” but nothing in the structure says how Is Player Visible? tells Move To Player which player, or where it was last seen. Every practical framework solves this the same way: a blackboard.

A blackboard is a key/value store attached to the agent (or the tree instance) that acts as the tree’s working memory. Leaves read from it and write to it; the tree structure itself never touches it.

   Perception system ──writes──▶ ┌─────────────────────────┐
                                 │        Blackboard        │
                                 │  target:    Player #2    │
                                 │  lastSeen:  (14, 3, 20)  │
                                 │  health:    34           │
                                 └─────────────────────────┘
                                    ▲               ▲
                            reads───┘               └───reads
                     Is Player Visible?          Move To (target)

The name comes from classic AI: independent specialists cooperating by reading and writing a shared blackboard, none of them talking to each other directly. That indirection is the entire point — Is Player Visible? and Move To Player stay reusable, single-purpose leaves precisely because neither knows the other exists.

Why not just use member variables?

You can, for a one-off agent. But the blackboard buys three things member variables don’t:

Scoping: not all keys are equal

Mature frameworks scope blackboard data, and the scopes matter:

ScopeLifetimeTypical contents
Agent / globalThe whole agentTarget, health, home position
Per-treeOne tree instance“Is this tree’s open-door subtree mid-way through?”
Per-nodeOne node in one treeA memory sequence’s running-child index, a cooldown’s timestamp

That last row is worth pausing on: the tree’s own bookkeeping lives in the blackboard too. In behavior3-family runtimes (the format this site’s editor exports), MemSequence stores which child was running, and Cooldown stores its last-fired time, in node-scoped blackboard memory — which is why one tree definition can drive a hundred agents simultaneously. The tree is stateless and shared; each agent’s blackboard carries all the per-agent state.

The same idea in each ecosystem

Patterns that keep it sane

A blackboard is, structurally, a bag of global variables — and it degrades exactly the way globals do if you’re careless. The patterns that prevent that:

  1. Write from few places, read from many. Perception/sensor code writes; tree leaves mostly read. When any node can write any key, you’ve rebuilt spaghetti with extra steps.
  2. Treat keys as an API. The set of keys is the contract between your tree design and your engine code. Name keys like you’d name public API, and document them next to the tree.
  3. Clear stale data deliberately. “Target died but target still points at the corpse” is the classic blackboard bug. Decide who nulls keys and when.
  4. Prefer a key per fact, not per behavior. lastKnownPlayerPosition serves chase, search, and aim; chaseDestination serves one branch and multiplies.

Try it

The survival-override example is a good specimen: health, target, and waypoint state all flow through the tree invisibly. Open it, and as you read each leaf, ask “what key would this read or write?” — health feeds Is Health Low?, perception writes the target Move To Player consumes, Next Waypoint advances an index Move To Waypoint reads. Sketching that column is most of the work of taking a design to Unity, Unreal, or a robot.

▶ Open the survival-override example in the editor

Recommended reading

Books that go deeper on behavior trees and game AI.

As an Amazon Associate, behaviortrees.com earns from qualifying purchases.