关于 unreal-behavior-trees
面向 UE5 NPC 决策开发的技能,涵盖 Behavior Trees 与 Blackboard 的组织和运行。内容包括分支响应、控制器接入及调试,目标版本为 UE 5.8。
主要功能
- 01创建 Behavior Tree 与 Blackboard 资产对
- 02使用复合节点组织逻辑
- 03通过装饰器控制分支
- 04用服务更新 Blackboard 值
- 05实现自定义任务和服务节点
- 06使用 Behavior Tree 调试器检查执行
适用场景
- 01在 UE5 中搭建敌人或 NPC 行为
- 02配置 AIController 运行 Behavior Tree
- 03让分支响应 Blackboard 键值变化
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill unreal-behavior-trees安装后在 Claude Code 中输入/unreal-behavior-trees确认已加载。
附带文件references/custom-bttask.md
详细介绍
虚幻行为树
在 UE5 中使用由黑板驱动的行为树编写 NPC 决策逻辑:通过复合节点构建树,用装饰器控制分支,用服务保持状态最新,并由 AIController 运行行为树。目标版本为 UE 5.8。
适用场景
- 构建敌人/NPC AI 时使用:创建
BT_/BB_资产对,构建 Selector/Sequence 分支,添加装饰器(条件)和服务(定期更新),编写自定义BTTask/BTService节点,或将 AIController 接入行为树。 - 项目使用了 Behavior Tree(
BT_)和 Blackboard(BB_)资产以及AAIController时使用。
不适用场景: AI 概念本身(FSM 与 BT 的比较、跨引擎内容)→ game-ai。纯导航/寻路数学属于引擎导航网格的范畴(BT 的 MoveTo 会用到它)。简单的一次性逻辑用小型状态机实现,可能比完整行为树更简单。
Behavior Tree 还是 StateTree? UE 5.8 同时提供这两者,Behavior Tree 并未弃用。StateTree 是 Epic 的通用分层状态机:它结合了 BT 风格的选择机制与显式的状态和转换。如果项目已经使用 StateTree 资产,或者 AI 自然地由一组具有明确转换的模式组成(巡逻 → 警戒 → 战斗),请先与用户确认,再考虑在其旁边添加 Behavior Tree。对于项目中已有 BT_/BB_ 资产的部分,继续使用 Behavior Tree。
核心工作流
- **创建资产对:**黑板(
BB_)存放有类型的键(AI 的记忆:TargetActor、LastKnownLocation、bIsInvestigating);行为树(BT_)引用该黑板。 - 接管并运行。
AAIController接管 Pawn 并调用RunBehaviorTree(BT),此调用也会初始化所引用的黑板。 - **使用复合节点构建结构。**Selector 按从左到右的顺序运行子节点,直到某个节点成功(优先级/回退:“攻击,否则追击,否则巡逻”)。Sequence 运行子节点,直到某个节点失败(全部执行:“移动到掩体 → 装弹 → 探身观察”)。Simple Parallel 同时运行一个主任务和一个次要任务。
- 使用装饰器控制分支,读取黑板键(例如,“有目标?”控制战斗分支)。设置 Observer Aborts,使树在键值变化时重新评估。
- 通过附加到分支的服务保持黑板内容最新——它们会定期触发(例如,通过视线检查更新
TargetActor),但仅在该分支处于活动状态时运行。 - 在任务中执行操作,任务会返回
Succeeded、Failed或InProgress(像MoveTo这样的延迟任务会稍后完成)。 - 验证在 PIE 期间使用 Behavior Tree 调试器——它会突出显示正在运行的节点并显示实时黑板值,让你准确看到当前执行的分支。
模式
1. 运行行为树的 AIController(C++)
void AEnemyAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
if (BehaviorTree) // UPROPERTY(EditAnywhere) TObjectPtr<UBehaviorTree>
RunBehaviorTree(BehaviorTree); // initializes & uses the Blackboard the BT references
}
2. 优先级树(节点结构)
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: Both 会让战斗分支在 TargetActor 被设置时立即中断巡逻,并在目标被清除时退出——这正是让 AI 产生灵敏反应的关键。
3. 从代码更新黑板(例如,看到玩家时)
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.
常见问题
- AI 始终不启动 — 该 Pawn 未被 AI 控制(将 Pawn 的 Auto Possess AI 设为 "Placed
in World or Spawned",并指定 AIController),或者从未调用
RunBehaviorTree。 MoveTo立即失败 — 关卡中没有 NavMesh(添加 Nav Mesh Bounds Volume),或者目标位于 NavMesh 之外。- 分支不会响应变化 — 门控 Decorator 的 Observer Aborts 设为 None;将其设为 Self/Lower Priority/Both,这样键值变化时行为树会重新评估。
- 任务让行为树卡住 — 自定义任务返回了
InProgress,却从未调用FinishLatentTask。务必完成所有延迟任务。 - Blackboard 键名拼写错误 —
SetValueAsObject("Taget", ...)会静默失效;键名和类型必须完全匹配,或者使用缓存的FBlackboardKeySelector。 - 混淆 Sequence 和 Selector — Sequence = AND(首次失败时停止);Selector = OR(首次成功时停止)。调换两者会反转行为。
参考资料
- 关于自定义 C++
UBTTaskNode(返回EBTNodeResult的即时和延迟ExecuteTask,以及FBlackboardKeySelector),请阅读references/custom-bttask.md。 - 主要文档:"Behavior Trees in Unreal Engine"
(
https://dev.epicgames.com/documentation/en-us/unreal-engine/behavior-trees-in-unreal-engine)。
相关技能
game-ai— 与引擎无关的 AI 设计(FSM、BT、转向、寻路选择)。unreal-cpp-gameplay— 用 C++ 编写 AIController 和 Pawn 类。fps-shooter/tower-defense— 组合敌方 AI 的游戏类型。
评论
支持 Markdown