行为树与效用 AI
两种互补的方式来组织 NPC 决策,以及如何组合它们。行为树(BT)将*结构化、有优先级、响应式*的逻辑表达为每步“tick”的树。效用 AI 通过用归一化曲线为动作评分并选择最佳项来回答“*我现在有多想要每个选项?*”。使用 BT 提供结构,在分级权衡重要的地方使用效用 AI,以交付可信的智能体。
本技能是 game-ai 的实现配套(后者帮助你*选择* FSM / BT / steering / pathfinding)。阅读 game-ai 选择模型;阅读本技能构建运行时。
何时使用
- 用于构建可复用的 BT 运行时:一个
Blackboard、Node基类、动作/条件叶子、Sequence/Selector/Parallel组合节点,以及装饰器(Inverter、Cooldown、Repeat)。 - 用于构建效用 AI 决策器:响应曲线、考虑因素,以及一个为动作评分并选择动作的评估器(max、softmax,或用于增加多样性的 weighted-random)。
- 用于构建混合 AI——一种 BT,其叶子将“选择哪种攻击 / 哪个目标”委托给效用评估器。
**何时*不要*使用:** 若要在 FSM、BT、steering 或 pathfinding 之间选择,以及用于 A*/navmesh 路由,请使用 game-ai。对于 Unreal 基于资源的 BehaviorTree/Blackboard、BTTask/BTService 和 AIController,请使用 unreal-behavior-trees。对于*移动* NPC 的 navmesh 智能体,请使用 unity-navmesh 或引擎的导航节点。
核心工作流
- 选择模型。 结构化、有优先级、可中断的行为 → BT。持续“为每个选项评分”的决策(目标选择、需求、物品选择)→ 效用。两者都需要 → 混合。
- 先设计 Blackboard。 每个智能体一个类型化的键/值存储,作为解耦节点的共享内存;叶子读写它,并且从不持有彼此引用。
- 编写叶子。 *条件*立即返回
Success/Failure;*动作*在帧间返回Running,直到完成。保持叶子小巧且副作用显式。 - 组合。
Selector= OR/回退(第一个非失败者胜出);Sequence= AND(在第一个非成功处停止);Parallel用于并发分支。用装饰器包装策略(invert、cooldown、repeat、force-success)。 - 对于 Utility: 枚举考虑因素,将每个原始事实映射到归一化 0..1 曲线,组合(带补偿的加权乘积,或加权求和),然后选择最大值——加入迟滞,使智能体不会在平局时反复摇摆。
- 有意地 tick。 每个*决策步*只 tick 一次树/评估器(通常比渲染慢)。在 ticks 之间保留
Running状态;调优时通过绘制活动路径和每个动作的分数来验证。
架构概览
行为树自顶向下、从左到右求值;每个节点将状态返回给其父节点:
flowchart TD
Root["Selector (root)"] --> Combat["Sequence: Combat"]
Root --> Patrol["Action: Patrol"]
Combat --> See["Condition: CanSeePlayer?"]
Combat --> InRange{"Selector: Reach"}
Combat --> Attack["Action: Attack (Running)"]
InRange --> Close["Condition: InAttackRange?"]
InRange --> MoveTo["Action: MoveToPlayer (Running)"]
效用 AI 是一条评分流水线——每个候选动作都会被评分,然后选择一个:
facts (distance, health, ammo…)
│ each fact → a normalized 0..1 response curve (consideration)
▼
score(action) = weight · combine(consideration_1 … consideration_n) # product+compensation or sum
▼
select: argmax · or softmax / weighted-random for variety · + hysteresis to avoid jitter
Status 是一个三值枚举,由每个节点共享——这是让树可组合的契约:
public enum Status { Success, Failure, Running }
public abstract class Node
{
public abstract Status Tick(Blackboard bb, float dt);
public virtual void Reset() { } // called when a parent abandons this subtree
}
// Selector = fallback/OR: return the first child that is not Failure.
public sealed class Selector : Composite
{
public override Status Tick(Blackboard bb, float dt)
{
for (; _current < Children.Count; _current++)
{
var s = Children[_current].Tick(bb, dt);
if (s != Status.Failure) return s; // Success or Running stops the scan
}
_current = 0;
return Status.Failure; // every child failed
}
}
对应的 Sequence(AND——在第一个非 Success 处停止)、Parallel、Blackboard、叶子基类,以及每个装饰器都在 references/behavior-tree-core.md 中。
一段代码示例:效用评分
// A consideration maps one raw fact to 0..1 through a response curve.
float Score(Blackboard bb)
{
float distance01 = Curves.InverseLerp01(bb.Get<float>("distToPlayer"), 20f, 2f); // near = 1
float health01 = Curves.Sigmoid(bb.Get<float>("health01"), k: 8f, mid: 0.4f); // hurt = low
// Product + compensation keeps a single 0 from vetoing while low values still dampen.
return Curves.CompensatedProduct(new[] { distance01, health01 });
}
完整曲线库(线性、二次、指数、logistic/sigmoid、smoothstep)、Consideration/UtilityAction 类型,以及 UtilityEvaluator 选择策略都在 references/utility-ai-system.md 中。
常见陷阱
- 每帧从根节点重新 tick 一个
Running动作会重启它。 返回Running并从中断处继续;只有当父节点真正放弃子树时才Reset()该子树。 - 每 tick 整体重新求值的深层树浪费时间并导致抖动。优先使用浅层树和*条件中止*(更高优先级条件可以中断较低分支)。
- 未归一化的考虑因素。 如果一条曲线输出 0..100,另一条输出 0..1,大的会占主导。每个考虑因素必须返回 0..1。
- 接近平局时的效用抖动。 加入迟滞:给当前运行中的动作一个小奖励,使智能体保持承诺而不是振荡。
- 每个 tick 分配节点、闭包或数组会造成 GC 峰值。在生成时构建一次树;保持每 tick 工作无分配。
参考
references/behavior-tree-core.md— Blackboard、Node/叶子基类、动作与条件叶子、Sequence/Selector/Parallel,以及装饰器库(完整 C#)。references/utility-ai-system.md— 响应曲线库、Consideration、UtilityAction,以及UtilityEvaluator(argmax、softmax、weighted-random、hysteresis)。references/practical-examples.md— 守卫 Patrol→Combat BT、村民基于需求的 Utility AI,以及混合智能体,作为可直接使用模板。references/best-practices-and-pitfalls.md— 内存管理、性能分析、避免深层树、事件驱动中止,以及将 Utility AI 与 BT 组合(混合架构)。
相关技能
game-ai— 在 FSM / BT / steering 之间选择;A* 与 navmesh 寻路。unreal-behavior-trees— Unreal 基于资源的 BT/Blackboard、任务、装饰器、服务。unity-navmesh— 执行“移动到”意图的NavMeshAgent。physics-tuning— 运动层的智能体半径、移动和碰撞响应。tower-defense、fps-shooter、rpg— 组合此决策层的类型。