CD Code Digest Hub /GTA V

行为任务、事件反应与环境活动 AI

范围:task/、event/、ai/,包含 task/Scenario/。总入口:Summary。

8 分钟阅读 8 个章节 2 张图

1. 设计思路与准确命名#

游戏 AI 由事件扫描与反应、任务树、任务内部状态机,以及运动/物理执行层协作。CTask 继承 RAGE aiTask;CTaskComplex 用有限状态机组织子任务创建、控制和切换。因此可以称其为层级任务与状态机体系,但不能未经核对就等同于现代工具中纯粹的 Selector/Sequence 行为树。

行为任务也不是 system/CTaskScheduler 的 CPU job。一个“进入车辆”任务可能持续多帧,等待路径、动画和座位;一次线程任务通常承担有明确输入输出的计算片段。混淆两者会误解生命周期与并行安全性。

2. 从事件到行动#

CEvent 提供过期、有效性、就绪、感知暴露、优先级、同类中断、响应任务创建等接口。事件“存在”不意味着一定要响应:它可能过期、不影响该角色、未达到感知条件,或被更高优先级事件压过。

CEventHandlerHistory 跟踪当前事件并比较新事件优先级;CEventHandler 的职责注释直接说明“处理 CPed 事件并产生 CTask 响应”。response 包含不同反应类别,PedIntelligence 暴露普通事件反应与 physical response 等访问接口。这样可以将受击、物理反应和主行为区分,而不必用一个全局枚举覆盖所有状态。

decision 目录把可编辑响应、flag、冷却等逻辑拆成数据和管理器。CPedIntelligence 的 response 记录还携带 cooldown 与位置/时间。设计目标是让相同刺激依据角色配置、历史和当前情况产生不同反应,同时避免每帧重复触发同一动作。

3. 复合任务内部如何推进#

CTaskComplex 声明三个核心虚函数:CreateFirstSubTask、ControlSubTask、CreateNextSubTask。实现中的 FSM 对应 State_CreateFirstSubTask、State_ControlSubTask、State_CreateNextSubTask 和退出状态。

这是概念化状态图;实际 abort、替换与恢复路径由任务基类和具体子类补充。m_pNewTaskToSet 暂存待设置任务,在进入控制状态时交接并清空,CleanUp 删除未完成交接的对象。这个细节表明任务切换包含明确的所有权转移,不能在外层重复删除子任务。

MayDeleteSubTaskOnAbort、MayDeleteOnAbort 根据默认中断后的状态决定是否可删除;注释说明支持恢复的任务可能需要保留子任务,供下一步使用。中断不是统一的“销毁整个任务树”,恢复能力也是具体任务的协议。

4. 多树与多阶段执行#

任务系统目录包含 Ped、Movement、Motion、Clone 等不同树;CVehicleTaskManager 还有 primary/secondary tree。不同树和优先级允许主行为、移动执行与附加行为协同,但也引入兼容性判断。CTaskComplex::IsValidForMotionTask 会在父任务不适合时继续询问子任务,表明运动层和高层行为的匹配并非仅检查根节点。

CTask 还暴露物理处理、摄像机设置、目标实体、ragdoll 和死亡处理等能力接口。行为语义会影响多个系统;例如正在执行某个动作时允许哪些相机设置、能否进入 ragdoll,需由任务实现明确表达。

clone 相关任务类型、TaskTreeClone 和网络任务创建入口说明远端角色不必完整重复本地所有高层决策。具体复制哪些状态由网络和任务克隆实现共同决定,不能把任务类存在直接等同于确定性全状态同步。

具体行为目录按语义继续拆分,阅读入口可按下表选择。这些类别共享 Task/System 的生命周期,但各自的成功、失败与中断条件由具体任务实现。

任务目录关注的执行边界
Default、General、Response默认行为、通用动作和事件响应
Movement、Motion目的地/路线意图与实际运动执行的衔接
Combat、Weapons、Crimes战斗、武器动作和犯罪相关反应
Vehicle角色进入、离开和处于载具中的行为,与 vehicleAi 中车辆自身任务分开
Animation、Physics脚本动画、物理反应和 NaturalMotion 相关任务
Scenario、Service环境活动与服务型行为
Helpers、Debug、System可复用辅助、调试和任务运行底座

5. Scenario 如何让世界“在生活”#

task/Scenario 包括点、点容器、区域、group、finder、manager、clustering、chaining、spawn history 和 vehicle manager。这是一套将空间内容与角色行为匹配的体系:点描述可进行的活动,finder 和管理器选择与协调,task 负责执行,chaining 支持活动连接,history 保存生成相关历史。

它与任务脚本的分工是:脚本可以控制特定叙事和任务流程,scenario 支持大量可复用环境活动。资源、角色类型、地点可用性和行为执行必须同时满足,故“地图上有活动点”并不保证每次都生成角色。

ai/ambient 下的 ConditionalAnim 和 AmbientModelSet 把动画与模型选择配置独立出来,降低为每种街头活动编写专用原生流程的需求。具体条件表达式和选择策略需查对应 .psc、实现与内容资源;本次不假设未提供内容数据的具体权重。

6. 感知与成本控制#

EntityScanner、spatialarray、ExpensiveProcess 是 AI 公共辅助;角色 AI LOD 会分别削减事件、实体扫描、导航与智能更新。这样可以把昂贵查询摊开,而非让所有 NPC 在同一帧进行全量世界扫描。

维护时最容易破坏的是时间语义:分时任务不能把“调用次数”当作绝对时间;异步查询结果可能在任务切换后返回;高优先级事件仍需保证可中断或等待安全点。事件有效性、任务所有权与 pending 查询清理应一起检查。

7. 一条实用阅读路线#

分析“NPC 听见事件后逃跑”,先确定 event 类型和感知条件,再看 decision maker 如何选择反应,随后追踪 response 创建的 task,进入具体 FSM 和导航请求,最后看 motion/animation 的执行。若角色不行动,依次区分未感知、未选中、被优先级覆盖、等待资源、求路失败和运动受阻,避免把所有现象都归咎于寻路。

本文从核心接口与实现还原机制,未逐个审计数百个具体任务,也未运行 AI 场景。各任务的专用行为仍以其子类实现为准。

8. 源码依据#

源码重点
Task.hCTask : aiTask 与跨系统接口
TaskComplex.h三个子任务接口及 abort 恢复约定
TaskComplex.cppFSM、待设置子任务与清理
TaskManager.hPed/Vehicle manager、主次任务树
Event.h有效性、优先级、响应创建
EventHandler.h历史、事件仲裁和响应
ScenarioManager.h场景活动管理入口

关联:角色、导航、动画。