Core Concepts
Node Types
Section titled “Node Types”Composite Nodes
Section titled “Composite Nodes”Control the execution flow of child nodes.
Sequence
Section titled “Sequence”Executes children in order. Fails if any child fails.
.sequence('AttackSequence') .condition('hasTarget') // If false, sequence fails .action('moveToTarget') // If fails, sequence fails .action('attack') // If succeeds, sequence succeeds.end()Selector
Section titled “Selector”Tries children until one succeeds. Fails if all children fail.
.selector('FindTarget') .action('findNearestEnemy') // Try first .action('findNearestItem') // Try if first fails .action('wander') // Fallback.end()Parallel
Section titled “Parallel”Executes all children simultaneously.
.parallel('CombatActions', { successPolicy: 'all', // 'all' | 'any' failurePolicy: 'any' // 'all' | 'any'}) .action('playAttackAnimation') .action('dealDamage') .action('playSound').end()Leaf Nodes
Section titled “Leaf Nodes”Action
Section titled “Action”Performs a specific task.
.action('attack', { damage: 10 })Condition
Section titled “Condition”Checks a condition without side effects.
.condition('isHealthLow', { threshold: 30 })Decorator Nodes
Section titled “Decorator Nodes”Modify child behavior.
// Invert result.inverter() .condition('isEnemy').end()
// Repeat until failure.repeatUntilFail() .action('patrol').end()
// Timeout.timeout(5000) .action('searchForTarget').end()Task Status
Section titled “Task Status”Every node returns one of these statuses:
| Status | Description |
|---|---|
Success | Task completed successfully |
Failure | Task failed |
Running | Task still in progress |
import { TaskStatus } from '@esengine/behavior-tree';
class MyAction implements INodeExecutor { execute(context: NodeExecutionContext): TaskStatus { if (/* completed */) return TaskStatus.Success; if (/* failed */) return TaskStatus.Failure; return TaskStatus.Running; // Still working }}Blackboard System
Section titled “Blackboard System”Local vs Global
Section titled “Local vs Global”// Local blackboard - per behavior tree instanceruntime.setBlackboardValue('localVar', value);
// Global blackboard - shared across all treesruntime.setGlobalBlackboardValue('globalVar', value);Variable Access in Executors
Section titled “Variable Access in Executors”class PatrolAction implements INodeExecutor { execute(context: NodeExecutionContext): TaskStatus { // Read from blackboard const target = context.runtime.getBlackboardValue('patrolTarget'); const speed = context.runtime.getBlackboardValue('moveSpeed');
// Write to blackboard context.runtime.setBlackboardValue('lastPosition', currentPos);
return TaskStatus.Success; }}Execution Context
Section titled “Execution Context”interface NodeExecutionContext { readonly node: IBehaviorTreeNode; // Current node data readonly runtime: BehaviorTreeRuntimeComponent; // Runtime state readonly entity: Entity; // Owner entity readonly scene: Scene; // Current scene readonly deltaTime: number; // Frame delta time}Architecture Overview
Section titled “Architecture Overview”BehaviorTreeData (Pure Data) │ ├── Serializable JSON structure ├── Node definitions └── Blackboard schema
BehaviorTreeRuntimeComponent (State) │ ├── Current execution state ├── Blackboard values └── Node status cache
BehaviorTreeExecutionSystem (Logic) │ ├── Drives tree execution ├── Manages node traversal └── Calls INodeExecutor.execute()
INodeExecutor (Behavior) │ ├── Stateless design ├── Receives context └── Returns TaskStatus