AI 感知:守卫看见了什么,又以为看见了什么
AI Perception Concepts
守卫凭什么知道你在哪
潜行游戏里,你贴着墙根溜过去,守卫没有回头;你一冒头,它立刻喊了一声冲过来。守卫的 AI 不能直接去读「玩家坐标」这个变量:那样它要么像开了全图挂,隔着三堵墙也知道你在哪,要么只能把每一步都写成脚本。
真正的做法是给它装一层感知 (Perception):把世界上发生的事——看见、听见、挨打——变成 AI 可以用来做决策的信念。《游戏引擎架构》(GEA) 把感知和寻路、记忆并列为角色 AI 最底层的三件套,并且强调一条原则:perception is reality。玩家要是不觉得 NPC 聪明,内部模型再精致也白费。所以感知层不只要算得对,还要让玩家看得懂。
感知在整条 AI 管线里的位置是这样的:
flowchart LR W["世界里发生的事"] --> S["感知:视觉 / 听觉 / 伤害"] S --> K["知识修正(可选)"] K --> B["黑板 / Props:AI 的信念"] B --> D["决策:行为树、效用……"]
感知的结果先写进一块共享的记忆(黑板,或者 Halo 2 里叫 Props 的对象记忆),决策层只读这块记忆,不直接去翻世界。这一课先从最常见的感官——眼睛——讲起。
视觉:三道关
一个点要被守卫「看见」,得同时过三道关:
- 距离:在视距以内;
- 视野锥 (FOV):和守卫朝向的夹角小于视野半角;
- 视线 (Line of Sight, LOS):从守卫到这个点的连线不被墙挡住。
下面是俯视图。黄点是守卫,它会左右转头;鼠标就是你。亮的区域是守卫能发现你的地方,墙后面那块暗影就是被挡住的视线。把鼠标移进亮区,你会变成橙色。
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
canSee() 函数就是这三道关的直译。视野锥那一关没有去算角度,而是比较余弦:守卫朝向是单位向量 dir,指向目标的方向也归一化,两者的点积就是夹角的余弦,大于 cos(半角) 就说明在锥内。视线那一关把「守卫到目标」看成一条线段,检查它是否穿过墙所在的矩形——游戏里这一步通常是一次射线检测 (Raycast),依赖物理系统的碰撞查询。
两个圈:丢失半径为什么要比视距大
如果只有一个视距,你站在视距边缘来回晃,守卫就会「发现—丢失—发现—丢失」地抽搐。解决办法是用两个圈:进到视距以内才算发现,已经发现的目标要跑出更大的丢失半径才算丢失。虚幻引擎的视觉感官就有 Sight Radius 和 Lose Sight Radius 这一对参数,用的正是这种滞后 (Hysteresis)。
回到上面的画布,把「丢失半径」拖得比「视距」小,再把它拖大,看看两圈之间那一环怎么出现又消失。
不只是眼睛:听觉、伤害与阵营
视觉只是一种感官。常见的通道还有这些:
| 通道 | 要点 |
|---|---|
| 视觉 | 距离、视野半角、视线遮挡;丢失半径大于视距,防止抖动 |
| 听觉 | 噪声事件的强度随距离衰减;能不能被墙挡住,取决于具体实现 |
| 伤害 / 接触 | 即使没看见,挨了打也必须「知道有威胁」 |
| 阵营 / 团队 | 过滤敌友;可选地预测目标未来的位置 |
虚幻引擎把这些做成可以配置的感官:被感知的一方挂一个刺激源 (Stimuli Source) 组件自动注册,AI 控制器上的感知组件收到更新后触发回调,回调里通常就是去改黑板的键。每条刺激带着 Age、Strength、位置等信息;通用参数 Max Age 决定多久以后遗忘,设成 0 表示永不遗忘(还要在项目设置里开启 Forget Stale Actors)。
信念不等于真相
感知写进记忆的,是 AI 以为的世界。Halo 2 的 AI 把对每个目标的感知结果存在叫 Props 的对象记忆里,存的是过滤过的状态,允许和真实世界不一致。
Props 里还会挂一些和这个目标有关的记录,比如「是否已经搜过」。黑板上常见的「上次看见的位置」「噪声位置」也是同一种信念:它们是感知的结果,不是世界的真相。
「哪里最好」:环境查询
感知回答的是「察觉到了什么」。可战斗里常常还要回答另一个问题:站到哪里最好——哪个掩体能挡子弹,哪个位置能打到玩家。这需要在一批候选位置上采样、过滤、打分。
虚幻引擎的环境查询系统 (Environment Query System, EQS) 就是这个思路:生成器 (Generator) 产生候选项,测试 (Test) 负责过滤和打分,最后返回最好的一项。它的思想来自 UE3 的环境战术查询 (Environment Tactical Query)。
下面的画布里,网格上每个点都是候选位置,守卫要找一个看得见你、又离自己尽量近的点。流程是:先用距离过滤(便宜),再测试到你的视线(贵,相当于一次射线检测),最后按离守卫的远近打分。大点分高,暗淡的小点是被过滤掉的,橙色是最终选中的位置。拖着鼠标绕到墙后面,看看选中的点怎么跟着变。
也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。
EQS 把这个顺序做成了规则:过滤类的测试总是先于打分类的测试执行,好让需要打分的项尽量少,所以测试添加的先后无关紧要。开销大致是「候选项数 × 每个测试的成本」,射线类的可见性测试最贵,应该先用便宜的距离过滤缩小集合。
在游戏里怎么用
取舍与常见的坑
小结与练习
- 「看见」要过三道关:距离、视野锥、视线遮挡,按便宜到昂贵的顺序检查;
- 视距和丢失半径组成滞后,避免目标在边缘晃动时状态抽搐;
- 感知写进记忆的是信念,可以和真相不一致,这让 AI 能被骗、会搜索;
- 「站哪里最好」交给环境查询:生成候选、先过滤后打分。
练习:在第一个画布里给守卫加一个「贴身就会察觉」的小圈:距离很近时,不管在不在视野锥里都算发现。提示:改 canSee() 的返回值,再画一个圈帮自己看清范围。想一想,这个圈该不该被墙挡住?
感知层把世界变成 AI 可决策的信念:视觉(视线、视野锥、丢失滞后)、听觉、伤害、接触等刺激,经衰减与遗忘写入知识/黑板。GEA 将其与寻路、记忆并列底层;「perception is reality」要求玩家可见结果与感知一致。
在管线中的位置
感知 →(可选)知识修正 → 黑板/Props → 决策。没有感知,决策只能开挂读全图,或完全脚本。(GEA4 Vol II §18.2.3 Artificial Intelligence(摘录笔记))
常见通道
| 通道 | 概念要点 |
|---|---|
| 视觉 | 距离、FOV 半角、LOS 遮挡;Lose 半径 > Sight 半径防抖动 |
| 听觉 | 噪声事件强度随距离衰减;可被墙体阻挡(实现相关) |
| 伤害 / 接触 | 强制「知道有威胁」即使未见 |
| 阵营 / 团队 | 过滤敌友;预测未来位置(可选) |
UE 将这些做成可配置 sense + Stimuli Source,回调更新黑板——实现见 AI 感知、EQS 与导航。(AI Perception)
信念 ≠ 真相
Isla:Props 存过滤后的目标状态,允许 AI 相信错误位置(目标已走开仍搜旧点)——这是可被骗与「看起来在搜」的基础。(Handling Complexity in the Halo 2 AI(笔记))
「哪里最好」:环境查询
感知回答「察觉到什么」;战术位置常另需采样打分(掩体、射击位)。UE EQS:生成器 → 过滤 → 打分,思想来自环境战术查询。(Environment Query System Overview)引擎无关层:在候选集上做多测试加权,先便宜过滤再贵射线。
与空间/碰撞
LOS 与听力遮挡依赖 碰撞查询;广域谁在附近依赖 空间分区。
取舍
- 感知过真(完美追踪)→ 玩家觉得作弊;过假 → 觉得傻。滞后半径、遗忘时间、听力误报是调「人格」的旋钮。
- 每帧全员全感知不可扩展:用事件、戳记、LOD(远距降频)。
出处
- GEA4 Vol II §18.2.3 Artificial Intelligence(摘录笔记) GEA4 §18.2.3
- Handling Complexity in the Halo 2 AI(笔记) Isla Props / 感知过滤
- AI Perception UE AI Perception
- Environment Query System Overview UE EQS(环境查询作为「哪里好」)