一、AI 在 UE 里的位置
和在 Gameplay 框架(第 8 篇)里讲过的角色层次关系对接:
AController├── APlayerController ← "人类玩家的遥控器"└── AAIController ← "AI 的遥控器" │ ├── Behavior Tree ← AI 的大脑(决策层) ├── Blackboard ← AI 的记忆(数据层) ├── EQS ← AI 的眼睛(感知层) └── AI Perception ← AI 的听觉/视觉(感知组件)关键:AI 用的 AIController 和人类用的 PlayerController 继承自同一个基类 AController。它们控制 Pawn 的方式完全一样——Possess(pawn) → 控制移动、旋转、技能。区别在于决策来源——人类来自输入设备,AI 来自 Behavior Tree。
二、Behavior Tree:AI 的决策树
1 核心节点类型
Root└── Selector(或:从左到右依次尝试,直到一个子节点成功) ├── Sequence(与:从左到右执行,直到一个子节点失败) │ ├── Decorator: 检查条件(如 "目标是否在攻击范围内") │ └── Task: 执行动作(如 "攻击目标") │ ├── Sequence │ ├── Decorator: 检查条件("听到了枪声") │ └── Task: 执行动作("移动到枪声位置") │ └── Sequence(如果前两个都失败,进入巡逻) └── Task: 执行动作("随机巡逻")三种复合节点:
| 节点 | 逻辑 | 行为 |
|---|---|---|
| Selector | ”或” | 依次尝试子节点,一个成功就停止 |
| Sequence | ”与” | 依次执行子节点,一个失败就全失败 |
| Simple Parallel | ”并行” | 主任务 + 后台任务同时跑 |
叶节点:
| 节点 | 做什么 |
|---|---|
| Task | 执行一个具体动作(MoveTo、PlayAnimation、ActivateAbility) |
| Decorator | 条件检查(“目标在范围内吗”)——附着在 Composite 或 Task 上 |
| Service | 后台持续运行的逻辑(“每 0.5 秒更新 Blackboard 里的目标位置”) |
2 执行模型:不是每帧重建决策树
重要区别:
不是每帧从 Root 重新评估整个树↓而是:当前 Task 未完成 → 继续执行(不重新评估上层 Selector/Sequence) 除非 Decorator 设置了 "Observer Aborts"Observer Aborts 是 AI 反应速度的关键:
Sequence "攻击目标" └── Decorator: CheckTargetInRange + Observer Aborts = Self → 当目标离开攻击范围时,自动中止整个 Sequence → 树回到上层 Selector → 切换到下一个分支(如"追击目标")没有 Observer Aborts,AI 会一直执行当前 Task 直到任务完成,不管外部条件如何变化。有了它,AI 在”攻击”过程中发现目标逃跑时,会立刻切换到追击。
3 Behavior Tree 的 Tick
不需要手动 Tick。引擎的 UBehaviorTreeComponent 每帧:
- 检查当前活跃的 Decorator 的 Observer Aborts 条件
- 触发 Abort → 回退到上层节点重新评估
- 如果当前 Task 仍在执行且未被 Abort → 跳过重新评估
Service 的 Tick:附着在 Composite 节点上,以某个频率(如 0.5 秒)执行,更新 Blackboard 数据。
三、Blackboard:AI 的共享记忆
1 Blackboard 存储什么
Blackboard(键值对)├── TargetActor (Object) → 当前目标是谁├── TargetLocation (Vector) → 目标在哪├── LastKnownPosition (Vector) → 目标最后被看到的位置├── HomeLocation (Vector) → 巡逻起点├── AmmoCount (Int) → 弹药├── bIsAlerted (Bool) → 是否警觉└── bHasWeapon (Bool) → 是否有武器2 谁写 Blackboard
| 写入方 | 例子 |
|---|---|
| AI Perception | 看到敌人 → 写 TargetActor |
| Service | 每 0.5 秒计算”最近敌人”→ 更新 TargetActor |
| Task | 移动到目标后 → 写 bAtDestination = true |
| EQS | 查询最佳掩体位置 → 写 BestCoverLocation |
| C++ / BP | 收到伤害事件 → 写 bIsAlerted = true |
Blackboard 是 AI 各子系统之间唯一的通信方式。 Behavior Tree 读它来决策、Perception 写它来汇报、EQS 写它来提供空间信息。
四、EQS(Environment Query System)——AI 的眼睛
1 EQS 是什么
AI 经常需要回答”最好的 X 在哪”——最好的掩体、最好的狙击点、最好的弹药箱位置。EQS 用打分系统来评估空间中的候选点:
查询:"离我 10-50 米内,有掩体、离敌人远、离我近的点,哪个最好?"
步骤:1. Generate:生成候选点(以我为中心的网格,间距 2 米)2. Test(对每候选点打分): ├── DistanceTo: Enemy → 离敌人越远,分越高 ├── DistanceTo: Self → 离自己越近,分越高 └── Dot: 掩体方向 vs 敌人方向 → 掩体在敌人方向上的,分越高3. 选出最高分 → 写入 Blackboard.BestCoverLocation2 在 Behavior Tree 里调用 EQS
Behavior Tree: Selector: └── Sequence "寻找掩体" ├── Task: RunEQSQuery (CoverQuery) │ → 打分完成,结果写入 Blackboard.BestCoverLocation └── Task: MoveTo(Blackboard.BestCoverLocation)整个掩体寻找的逻辑只有两个 Task 节点——查询和移动。EQS 负责”找哪”,MoveTo 负责”走过去”。
五、RPG 卫兵的 AI——怎么设计
一个 RPG 卫兵需要根据距离、视线和警戒状态做决策。把 Behavior Tree 的思维方式用过来:
AI Guard Brain(Behavior Tree 风格): Selector: ├── Sequence "战斗策略"(目标在攻击范围内且自身有法力) │ └── Task: 释放远程技能 │ ├── Sequence "追击策略"(已经发现目标但距离较远) │ └── Task: MoveTo(Blackboard.TargetActor) │ └── Sequence "巡逻策略"(默认) └── Task: MoveTo(Blackboard.PatrolPoint)这里 EQS 可以用来寻找掩体、巡逻点或最佳攻击位置,而 Behavior Tree + Blackboard 负责把“目标是否可见”“当前生命值”“是否在攻击范围内”放进 Blackboard,再根据条件选择策略。
六、总结
| 概念 | 一句话 |
|---|---|
| AIController | AI 的”遥控器”——和 PlayerController 同一基类,Possess Pawn 控制一切 |
| Behavior Tree | Selector(或) / Sequence(与) / Task(动作) / Decorator(条件) / Service(后台) |
| Observer Aborts | 外部条件变化时自动中止当前执行——AI 反应速度的关键 |
| Blackboard | AI 的共享记忆——决策层、感知层、EQS 的唯一通信渠道 |
| EQS | 空间打分系统——“最好的 X 在哪” → 生成候选点 → 逐个打分 → 选最高分 |
| AI Perception | 视觉/听觉/伤害感知——检测到刺激 → 写 Blackboard |
UE 的 AI 框架不只是给 FPS 的敌人用的。Behavior Tree 的决策树思维 + Blackboard 的数据共享 + EQS 的打分系统——这套架构可以被复用到 RPG 卫兵、队友 AI、对话系统,甚至自动化测试中。