导航、道路与空间查询
范围:pathserver/、vehicleAi/pathfind*、道路连接与 control/gps*。总入口:Summary。
1. 两类导航表达#
游戏同时使用面向角色可行走空间的 navmesh,以及面向车辆/GPS 的道路节点和连接。前者关注表面、障碍、跳爬等可达性;后者关注道路拓扑、车道、方向与转弯。两者可以协作,但不能用一个“全局寻路算法”解释全部移动。
| 体系 | 游戏入口 | 核心数据与用途 |
|---|---|---|
| Navmesh 服务 | CPathServer : fwPathServer | 网格、多边形、路径点、waypoint flags、动态障碍、掩体 |
| 道路网络 | CPathFind : strStreamingModule | NodeAddress、node/link、路线、车道宽度/偏移、GPS |
| 路线执行 | VehicleNavigationHelper、角色/车辆任务 | 把路径变为运动意图和控制输入 |
| 离线生产 | NavMeshGenerator、RoadPathsGenerator | 构建导航内容;本报告只解释运行时接口 |
2. PathServer 是异步服务#
PathServer.h 的 Overview 明确描述:调用者提交路径请求得到 handle;请求进入队列,由 CPathServerThread 所封装的独立线程处理;结果保存至调用者取走,使用 Lock/Unlock 协议。当前接口名称为 IsRequestResultReady,注释中的 IsRequestReady 是概念说明,应以实际声明为准。
调用者取消或被删除时可以调用 CancelRequest,接口说明支持 pending、active 和 completed 状态。handle、结果锁和清理是资源协议的一部分;取到结果指针并不意味着可永久持有该缓冲区。
3. 请求不仅是起终点#
RequestPath 接收 request struct,或起终点、style flags、完成半径、实体等参数;LockPathResult 返回 waypoint flags 和 TPathResultInfo。这允许任务表达所需移动风格和能力,并让路径结果包含跨越或特殊动作信息。
PathServer 还提供 vantage point、navmesh line of sight、可行走 grid、掩体和生成点相关服务。Overview 特别指出 navmesh LOS 实质是 line of movement:它回答沿表面是否能通过,不能直接替代渲染可见性或精确物理射线。
RequestLineOfSight 声明处甚至注明 radius 参数“currently ignored”。阅读 API 不应只依据形参名称推断功能完整实现;若行为依赖半径,需要继续核对当前代码路径。该注释是源码中的局部限制,并不等于全部导航查询都忽略角色尺寸。
4. 搜索、动态障碍与路径整理#
PathServer_PathSearch.cpp 可见 A* 时间戳、访问多边形、启发式和多种移动代价;例如 flee、路面偏好和 enclosed-space 策略会改变成本。因而结果并不总是几何最短路线,而是满足行为约束并受策略评分影响的路线。本文不声称所有模式都满足经典 A* 的最优性条件。
PathServer_PathRequest.cpp 处理起终点 navmesh、最近已加载网格、动态对象模式、包围盒、tessellation 和 grid cache,说明动态障碍并非只在最终移动时处理。搜索得到的多边形序列还可进入 PathServer_PathStringPull.cpp 做路径整理;层次化、即时查询、对象和掩体逻辑分别拆文件,避免把所有策略挤进一个搜索函数。
这些机制有不同成本:动态障碍过多会增加测试和切分,频繁重新求路会增加队列压力,缓存命中依赖场景变化。源码保存 tessellation、LOS 和 cache hit 计数,提供了具体观测维度。
5. 流式世界中的导航#
navmesh 有 store、RequestAndEvict 和已加载范围判断,道路类直接继承 strStreamingModule。导航数据也受到 streaming 生命周期约束。远端目标无结果时,要区分拓扑不可达、能力不符、请求未完成和目标区域尚未装载。
任务可以调整网格区域开关,改变可达范围;动态对象还会影响通行。这使导航结果具有时间有效性。路径计算完成后,门、车辆或场景切换可能已经改变空间条件,执行层需要检测失败、重新请求或采用退路。
6. 道路、车道和 GPS#
CPathFind::PathQuery 和 DoPathSearch 暴露起始节点、目标节点、避开节点、最大请求节点、shortcut 等参数;输出还可包含 lane offset 与 lane width。道路线路与车辆位置之间存在横向车道映射,不能把道路中心线直接当作车辆最终轨迹。
GPS 有多种 GenerateRoutePointsForGps 重载、目标方向、忽略高度/NoGps 的条件,以及 asynchronous 选项;输出还记录是否忽略了单行限制。GenerateDirections 进一步将路线变为转向与街道信息。路径、导航提示和自动驾驶是不同消费者,展示路线并不意味着车辆 AI 正在按同样参数驾驶。
junctions、roadspeedzone、racingline、trafficlights 处理路口、速度、特定线路和交通信号。车辆任务还需要即时避障和控制器,这部分见 Vehicles。
7. 维护与诊断#
建议将一次失败记录成完整链路:请求参数/handle → 排队状态 → 网格/道路资源 → 搜索返回码 → 路径点与 flags → 行为执行结果。只输出“走不到”无法区分服务和执行层问题。
静态复核重点包括取消后的结果释放、任务重入时旧 handle 是否清理、网格卸载时索引有效性、路径风格与角色 NavCapabilities 是否一致。本文未执行导航生成器或游戏测试。
8. 源码依据#
| 源码 | 重点 |
|---|---|
| PathServer.h | Overview、异步请求、Lock/Unlock、Cancel、LOS |
| PathServer_PathRequest.cpp | 网格定位、动态对象、请求准备与计数 |
| PathServer_PathSearch.cpp | A* 相关结构和启发式成本 |
| PathServer_PathStringPull.cpp | 路径整理入口 |
| pathfind.h | streaming module、道路查询和 GPS |
| NavCapabilities.h | 角色导航能力 |