中EN
精修课概念页

AI 感知:守卫看见了什么,又以为看见了什么

AI Perception Concepts

更新于 2026-10-19 约 13 分钟游戏AI感知视线听力知识EQS

守卫凭什么知道你在哪

潜行游戏里,你贴着墙根溜过去,守卫没有回头;你一冒头,它立刻喊了一声冲过来。守卫的 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 的对象记忆),决策层只读这块记忆,不直接去翻世界。这一课先从最常见的感官——眼睛——讲起。

视觉:三道关

一个点要被守卫「看见」,得同时过三道关:

  1. 距离:在视距以内;
  2. 视野锥 (FOV):和守卫朝向的夹角小于视野半角;
  3. 视线 (Line of Sight, LOS):从守卫到这个点的连线不被墙挡住。

下面是俯视图。黄点是守卫,它会左右转头;鼠标就是你。亮的区域是守卫能发现你的地方,墙后面那块暗影就是被挡住的视线。把鼠标移进亮区,你会变成橙色。

守卫的眼睛:距离、视野锥、视线遮挡0.0s
改一改

也可以直接改右边的代码:停手约 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 的对象记忆里,存的是过滤过的状态,允许和真实世界不一致。

守卫?守卫以为你在这里你其实在这里
你在守卫的注视下溜到了墙后。守卫的记忆里,你还在「上次看见的位置」,于是它走过去搜那里——这正是玩家能骗过 AI、AI 也显得「在找人」的原因。

Props 里还会挂一些和这个目标有关的记录,比如「是否已经搜过」。黑板上常见的「上次看见的位置」「噪声位置」也是同一种信念:它们是感知的结果,不是世界的真相。

「哪里最好」:环境查询

感知回答的是「察觉到了什么」。可战斗里常常还要回答另一个问题:站到哪里最好——哪个掩体能挡子弹,哪个位置能打到玩家。这需要在一批候选位置上采样、过滤、打分。

虚幻引擎的环境查询系统 (Environment Query System, EQS) 就是这个思路:生成器 (Generator) 产生候选项,测试 (Test) 负责过滤和打分,最后返回最好的一项。它的思想来自 UE3 的环境战术查询 (Environment Tactical Query)。

下面的画布里,网格上每个点都是候选位置,守卫要找一个看得见你、又离自己尽量近的点。流程是:先用距离过滤(便宜),再测试到你的视线(贵,相当于一次射线检测),最后按离守卫的远近打分。大点分高,暗淡的小点是被过滤掉的,橙色是最终选中的位置。拖着鼠标绕到墙后面,看看选中的点怎么跟着变。

一次简化的环境查询:生成、过滤、打分
改一改

也可以直接改右边的代码:停手约 0.3 秒会自动重新运行;改坏了点「还原代码」。

evaluate() 里过滤在前、打分在后:被距离筛掉的点根本不会去做视线测试。

EQS 把这个顺序做成了规则:过滤类的测试总是先于打分类的测试执行,好让需要打分的项尽量少,所以测试添加的先后无关紧要。开销大致是「候选项数 × 每个测试的成本」,射线类的可见性测试最贵,应该先用便宜的距离过滤缩小集合。

在游戏里怎么用

取舍与常见的坑

小结与练习

  • 「看见」要过三道关:距离、视野锥、视线遮挡,按便宜到昂贵的顺序检查;
  • 视距和丢失半径组成滞后,避免目标在边缘晃动时状态抽搐;
  • 感知写进记忆的是信念,可以和真相不一致,这让 AI 能被骗、会搜索;
  • 「站哪里最好」交给环境查询:生成候选、先过滤后打分。

练习:在第一个画布里给守卫加一个「贴身就会察觉」的小圈:距离很近时,不管在不在视野锥里都算发现。提示:改 canSee() 的返回值,再画一个圈帮自己看清范围。想一想,这个圈该不该被墙挡住?

  1. GEA4 Vol II §18.2.3 Artificial Intelligence(摘录笔记) GEA4 §18.2.3
  2. Handling Complexity in the Halo 2 AI(笔记) Isla Props / 感知过滤
  3. AI Perception UE AI Perception
  4. Environment Query System Overview UE EQS(环境查询作为「哪里好」)

相关页面

游戏开发游戏 AI 决策管线Game AI Sense-Decide-Act Pipeline游戏 AI(与生成式 DNN 不同)通常按 感知 → 决策 → 执行 分层:底层是寻路、感知与记忆;中层是角色控制(对接动画/物理);上层是目标与决策(行为树、效用、规划等)。GEA 强调「perception is reality」——玩家看不见的内部聪明不算数。游戏开发黑板架构Blackboard Architecture黑板 (Blackboard) 是多模块共享的「工作记忆」:感知写入、决策读取、任务更新键值,避免各子系统用私有状态互相耦合。行为树的 Data Context、GOAP 的 Working Memory、Halo 的 Props,都是同一思想的变体。游戏开发 · UE5AI 感知、EQS 与导航AI Perception, EQS & NavigationAI 的感官层由三块组成:AI 感知 (AI Perception) 组件挂在 AIController 上监听视觉/听觉/伤害等刺激并更新黑板;环境查询系统 (EQS) 用生成器产生候选项、先过滤后打分,回答「哪里最好」;导航系统从碰撞几何生成分瓦片的导航网格 (NavMesh),按多边形代价寻路,并提供 RVO 与 Detour Crowd 避让。它们为行为树/StateTree 提供输入。游戏开发 · UE5行为树与 StateTreeBehavior Tree & StateTreeUE 的 AI 决策有两套工具:行为树 (Behavior Tree) + 黑板 (Blackboard) 是事件驱动的,条件写成装饰器 (Decorator),用 Simple Parallel、Services 和 Observer Aborts 代替传统并行节点;StateTree 是结合了行为树选择器和状态机转换的通用分层状态机,只在转换触发时按需选择状态,激活路径上的任务并发运行,通过属性绑定传递数据,也是 Mass 的行为层。优先级抢占多的战斗 AI 适合行为树,状态显式、分层或大规模的场景适合 StateTree。游戏开发碰撞查询Collision Queries碰撞系统除了检测真实物体的接触,还要回答假设性问题:子弹从枪口朝某方向飞,先打中什么?车能否从 A 开到 B 不碰到东西?某半径内有哪些敌人?这类操作称为碰撞查询。最常见的是投射 (cast),也叫 trace 或 probe:沿射线或线段移动一个假想物体,看它会碰到什么;被投射的东西并不真正进入碰撞世界,不会影响其他物体(GEA4 卷 II 14.3.7)。游戏开发空间分区Spatial Partition空间分区 (Spatial Partition) 把对象按位置存进空间数据结构,使“找出某位置附近的对象”这类查询不必遍历所有对象,把 O(n) 或 O(n^2) 的操作降下来。最简单的是固定网格;还可以选层次结构(四叉树、BSP、k-d 树、BVH),以及边界固定或随对象自适应的划分方式。代价是对象移动时要更新结构,并且要额外占用内存。游戏开发寻路与导航理论基础Pathfinding & Navigation Theory寻路是在图上找代价可接受的路径:BFS / Dijkstra / A 是同一家族;NavMesh、路点、格子是不同的图构建方式。分层(走廊↔房间、扇区↔网格)与「全局路径 + 局部避障」把大规模导航拆开。A 本身不管编队、动态挤让与动画根运动。

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原