unreal-behavior-trees
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUnreal Behavior Trees
Unreal Behavior Trees
Author NPC decision-making in UE5 with Behavior Trees driven by a Blackboard: structure the
tree with composites, gate branches with decorators, keep state current with services, and run
it from an AIController. Targets UE 5.4+.
在UE5中基于Blackboard驱动的Behavior Trees编写NPC决策逻辑:使用组合节点构建树结构,用装饰器控制分支开启,通过服务保持状态更新,并通过AIController运行行为树。适用于**UE 5.4+**版本。
When to use
使用场景
- Use when building enemy/NPC AI: creating a /
BT_asset pair, structuring Selector/Sequence branches, adding decorators (conditions) and services (periodic updates), writing customBB_/BTTasknodes, or wiring an AIController to run the tree.BTService - Use when the project has Behavior Tree () and Blackboard (
BT_) assets and anBB_.AAIController
When not to use: the concept of AI (FSM vs BT vs steering, cross-engine) →
. Pure navigation/pathing math is engine navmesh (BT's uses it). Simple
one-off logic may be cheaper as a small state machine than a full tree.
game-aiMoveTo- 适用于构建敌人/NPC AI:创建/
BT_资源对、构建Selector/Sequence分支、添加装饰器(条件判断)和服务(周期性更新)、编写自定义BB_/BTTask节点,或者将AIController与行为树关联运行。BTService - 适用于项目中已存在Behavior Tree()、Blackboard(
BT_)资源以及BB_的场景。AAIController
不适用场景: AI概念层面的内容(有限状态机FSM vs 行为树BT vs 转向算法、跨引擎对比)→ 参考。纯导航/路径计算属于引擎导航网格(BT的节点会用到)。简单的一次性逻辑用小型状态机实现比完整行为树更高效。
game-aiMoveToCore workflow
核心工作流程
- Create the pair: a Blackboard () holds typed keys (the AI's memory:
BB_,TargetActor,LastKnownLocation); a Behavior Tree (bIsInvestigating) references that Blackboard.BT_ - Possess and run. An possesses the pawn and calls
AAIController, which also initializes the referenced Blackboard.RunBehaviorTree(BT) - Structure with composites. Selector runs children left→right until one succeeds (priority/fallback: "attack, else chase, else patrol"). Sequence runs children until one fails (do-all: "move to cover → reload → peek"). Simple Parallel runs one main task alongside a secondary.
- Gate branches with Decorators that read Blackboard keys (e.g. "Has Target?" guards the combat branch). Set Observer Aborts so the tree re-evaluates when the key changes.
- Keep the Blackboard current with Services attached to a branch — they tick periodically
(e.g. update via a sight check) only while that branch is active.
TargetActor - Do work in Tasks, which return ,
Succeeded, orFailed(latent tasks likeInProgressfinish later).MoveTo - Verify with the Behavior Tree debugger during PIE — it highlights the running node and shows live Blackboard values, so you see exactly which branch executes.
- 创建资源对: Blackboard()存储带类型的键值(即AI的记忆数据:
BB_、TargetActor、LastKnownLocation);Behavior Tree(bIsInvestigating)关联该Blackboard。BT_ - 控制并运行: 控制Pawn并调用
AAIController,该方法同时会初始化行为树关联的Blackboard。RunBehaviorTree(BT) - 用组合节点构建结构: **Selector(选择器)**从左到右执行子节点,直到某个子节点执行成功(优先级/ fallback逻辑:“攻击,否则追击,否则巡逻”)。**Sequence(序列节点)**执行子节点直到某个子节点执行失败(全执行逻辑:“移动到掩体 → reload → 探头”)。**Simple Parallel(简单并行节点)**同时执行一个主任务和一个次要任务。
- 用装饰器控制分支: 装饰器读取Blackboard键值(例如“是否有目标?”作为战斗分支的守卫条件)。设置Observer Aborts(观察者中断),以便当键值变化时重新评估行为树。
- 用服务保持Blackboard状态更新: 将服务附加到分支上——仅当该分支处于激活状态时,服务才会周期性执行(例如通过视野检测更新)。
TargetActor - 在任务中执行操作: 任务返回、
Succeeded或Failed(像InProgress这样的延迟任务会稍后完成)。MoveTo - 验证调试: 在PIE(Play In Editor)模式下使用行为树调试器——它会高亮当前运行的节点并显示Blackboard的实时值,让你清晰看到哪个分支在执行。
Patterns
常见模式
1. AIController that runs the tree (C++)
1. 运行行为树的AIController(C++实现)
cpp
void AEnemyAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
if (BehaviorTree) // UPROPERTY(EditAnywhere) TObjectPtr<UBehaviorTree>
RunBehaviorTree(BehaviorTree); // initializes & uses the Blackboard the BT references
}cpp
void AEnemyAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
if (BehaviorTree) // UPROPERTY(EditAnywhere) TObjectPtr<UBehaviorTree>
RunBehaviorTree(BehaviorTree); // initializes & uses the Blackboard the BT references
}2. A priority tree (node structure)
2. 优先级行为树(节点结构)
text
ROOT
└── Selector (try combat, else investigate, else patrol)
├── Sequence [Decorator: Blackboard 'TargetActor' Is Set, Observer Aborts: Both]
│ ├── Task: MoveTo (TargetActor) // latent: returns InProgress then Succeeded
│ └── Task: Attack
├── Sequence [Decorator: 'LastKnownLocation' Is Set]
│ ├── Task: MoveTo (LastKnownLocation)
│ └── Task: Wait (3s) + clear key
└── Task: Patrol (BTTask_FindPatrolPoint -> MoveTo)Observer Aborts: BothTargetActortext
ROOT
└── Selector (try combat, else investigate, else patrol)
├── Sequence [Decorator: Blackboard 'TargetActor' Is Set, Observer Aborts: Both]
│ ├── Task: MoveTo (TargetActor) // latent: returns InProgress then Succeeded
│ └── Task: Attack
├── Sequence [Decorator: 'LastKnownLocation' Is Set]
│ ├── Task: MoveTo (LastKnownLocation)
│ └── Task: Wait (3s) + clear key
└── Task: Patrol (BTTask_FindPatrolPoint -> MoveTo)Observer Aborts: BothTargetActor3. Updating the Blackboard from code (e.g. on seeing the player)
3. 通过代码更新Blackboard(例如发现玩家时)
cpp
void AEnemyAIController::SetTarget(AActor* Target)
{
if (UBlackboardComponent* BB = GetBlackboardComponent())
BB->SetValueAsObject(TEXT("TargetActor"), Target); // key name must match the BB asset
}
// Clear with BB->ClearValue(TEXT("TargetActor")); to drop back to a lower-priority branch.cpp
void AEnemyAIController::SetTarget(AActor* Target)
{
if (UBlackboardComponent* BB = GetBlackboardComponent())
BB->SetValueAsObject(TEXT("TargetActor"), Target); // key name must match the BB asset
}
// Clear with BB->ClearValue(TEXT("TargetActor")); to drop back to a lower-priority branch.Pitfalls
常见陷阱
- AI never starts — the pawn isn't possessed (set the Pawn's Auto Possess AI to "Placed
in World or Spawned" and assign the AIController), or was never called.
RunBehaviorTree - instantly fails — no NavMesh in the level (add a Nav Mesh Bounds Volume), or the target is off the navmesh.
MoveTo - Branch doesn't react to changes — the gating Decorator's Observer Aborts is set to None; set it to Self/Lower Priority/Both so the tree re-evaluates when the key changes.
- A task hangs the tree — a custom task returned and never calls
InProgress. Always complete latent tasks.FinishLatentTask - Blackboard key typos — silently does nothing; match the key name and type exactly, or use a cached
SetValueAsObject("Taget", ...).FBlackboardKeySelector - Sequence vs Selector confusion — Sequence = AND (stops on first failure); Selector = OR (stops on first success). Swapping them inverts the behaviour.
- AI从未启动——Pawn未被控制(将Pawn的Auto Possess AI设置为“Placed in World or Spawned”并指定AIController),或者从未调用方法。
RunBehaviorTree - 立即失败——关卡中没有导航网格(添加Nav Mesh Bounds Volume),或者目标不在导航网格上。
MoveTo - 分支不响应变化——控制分支的装饰器的Observer Aborts设置为None;将其设置为Self/Lower Priority/Both,以便当键值变化时重新评估行为树。
- 任务阻塞行为树——自定义任务返回但从未调用
InProgress。延迟任务必须始终完成。FinishLatentTask - Blackboard键值拼写错误——会静默失败;键值名称和类型必须与Blackboard资源完全匹配,或使用缓存的
SetValueAsObject("Taget", ...)。FBlackboardKeySelector - 混淆Sequence和Selector——Sequence = 逻辑与(遇到第一个失败则停止);Selector = 逻辑或(遇到第一个成功则停止)。两者互换会导致行为完全相反。
References
参考资料
- For a custom C++ (instant and latent
UBTTaskNodereturningExecuteTask, with aEBTNodeResult), readFBlackboardKeySelector.references/custom-bttask.md - Primary docs: "Behavior Trees in Unreal Engine"
().
https://dev.epicgames.com/documentation/en-us/unreal-engine/behavior-trees-in-unreal-engine
- 如需了解自定义C++ (即时任务和延迟任务的
UBTTaskNode返回ExecuteTask,搭配EBTNodeResult),请阅读FBlackboardKeySelector。references/custom-bttask.md - 官方主文档:“Behavior Trees in Unreal Engine”
().
https://dev.epicgames.com/documentation/en-us/unreal-engine/behavior-trees-in-unreal-engine
Related skills
相关技能
- — engine-agnostic AI design (FSM, BT, steering, pathfinding choices).
game-ai - — the AIController and pawn classes in C++.
unreal-cpp-gameplay - /
fps-shooter— genres that compose enemy AI.tower-defense
- ——与引擎无关的AI设计(有限状态机FSM、行为树BT、转向算法、路径选择)。
game-ai - ——C++中的AIController和Pawn类。
unreal-cpp-gameplay - /
fps-shooter——需要组合敌人AI的游戏类型。tower-defense