车辆 AI、路网、交通灯、录像与 GPS
本页解释车辆如何“认路和开车”:框架层 fwvehicleai 定义的路网节点/链接/区域二进制格式;游戏层 CPathFind(全局单例 ThePaths)如何作为流式模块按区域装载路网、如何用 A* 做路线搜索;CVehicleIntelligence 与车辆任务树(vehicleAi/task)如何把“目标”变成节点列表、follow route 与每帧的转向/油门/刹车;避障与延迟(多线程)任务;路口 CJunctions 与交通灯 CTrafficLights 的相位逻辑;以及车辆录像(CVehicleRecordingMgr)、航点录像(CWaypointRecording)、路线池(Route.h)与玩家 GPS(CGps)。
父页面见 vehicle-architecture.md;dummy/superdummy 如何依赖本页的 follow route 见 vehicle-physics-handling-damage.md 第 4.2、8 节。
背景与相关页面#
- ped 侧驾驶/上下车任务(
CTaskControlVehicle、CTaskEnterVehicle等,它们向车辆任务树下发车辆任务):归 ../07-ai-tasks/task-catalogue.md;通用任务框架aiTask/CTaskFSM:见 ../07-ai-tasks/task-system.md。 - 导航网格寻路(
CPathServer,车辆导航网格任务CTaskVehicleGoToNavmesh会用到):见 ../07-ai-tasks/navigation-and-pathserver.md。 - 流式引擎
strStreamingModule:见 ../04-rage-framework/streaming-engine.md;资源放置pgRscBuilder:见 ../02-rage-core/paging-and-resources.md。 - 通缉/调度对警车 AI 的驱动:见 ../20-gameplay/wanted-crime-dispatch.md;回放系统(与车辆录像不同):见 ../19-persistence-replay/replay-and-video.md;小地图 GPS 渲染:见 ../18-frontend-ui/pause-menu-and-hud.md。
- 车辆任务的网络序列化(
CTaskVehicleSerialiser)与迁移:归 ../17-network-sync/network-object-model.md。
相关源码文件#
| 文件 | 作用 |
|---|---|
rage/framework/src/fwvehicleai/pathfindtypes.h/.cpp、pathregion.psc | CNodeAddress、CPathNode、CPathNodeLink、CPathVirtualJunction、CPathRegion(资源格式) |
game/vehicleAi/pathfind.h/.cpp、pathfind_shared.cpp、Pathfind_Build.*、PathfindNodeSearchJob.cpp、PathfindNodeSearchSPU*.{job,cpp} | CPathFind/ThePaths:流式、查询、A* 搜索、GPS 路线、离线构建、异步最近节点搜索 |
game/vehicleAi/VehicleIntelligence*.*、VehMission.h、VehicleNodeList.* | 车辆 AI 本体、任务/驾驶标志枚举、节点列表 |
game/vehicleAi/task/* | 车辆任务(巡航、前往、避障、停车、追逐、飞行、玩家驾驶、录像跟随…)与延迟任务 |
game/task/System/TaskHelpers.h/.cpp | CPathNodeRouteSearchHelper、CRoutePoint、CVehicleFollowRouteHelper |
game/vehicleAi/junctions.*、junctions.psc、JunctionEditor.* | 路口实例、模板、相位、铁路道口 |
game/control/trafficlights.* | 交通灯周期、渲染、TrafficLightInfos 扩展 |
game/control/record.*、rage/framework/src/fwcontrol/record.h | 车辆录像录制与回放 |
game/control/WaypointRecording*.*、rage/framework/src/fwcontrol/WaypointRecordingRoute.h | 航点录像(ped/车辆) |
game/control/Route.* | CPointRoute/CPatrolRoute 池 |
game/control/gps.* | 玩家 GPS 槽位 |
game/vehicleAi/driverpersonality.*、FlyingVehicleAvoidance.*、roadspeedzone.*、pathzones.*、racingline.*、VehicleNavigationHelper.* | 驾驶员个性、飞行器互相避让、道路限速区、路径区域、赛车线、无路网导航辅助 |
1. 分层视图#
证据:车辆任务管理器 src/dev_ng/game/task/System/TaskManager.h:76-92;CVehicleIntelligence::Process 调用 m_TaskManager.Process src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1104-1106;巡航任务持有路线搜索助手与 follow route src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:239-247;路线搜索调用 ThePaths.DoPathSearch src/dev_ng/game/task/System/TaskHelpers.cpp:2974-2990;区域数组 src/dev_ng/game/vehicleAi/pathfind.h:1175;节点列表容量 src/dev_ng/game/vehicleAi/VehicleNodeList.h:55-56;follow route 容量 src/dev_ng/game/task/System/TaskHelpers.h:1200;避障任务的延迟回调 src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:286-288;dummy 用 follow route 采样虚拟路面 src/dev_ng/game/Vehicles/Automobile.cpp:8364-8436。ped→车辆任务的下发细节归 07 章,图中该边仅示意。
2. 路网数据格式(fwvehicleai)#
2.1 区域与节点地址#
地图被切成 PATHFINDMAPSPLIT × PATHFINDMAPSPLIT = 32 × 32 = 1024 个区域,每区最多 MAXNODESPERREGION = 10240 个节点、MAXLINKSPERREGION = 32768 条链接、256 个路口、65536 个高度样本 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:30-41。坐标压缩:XY 以 s16 存储、×4(0.25m 精度),Z 以 u16 存储、×32(注释:从 64 降到 32 以支持 ±1024m 高度)src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:43-56。
CNodeAddress 是 32 位的 {region:16, index:16},全 1 表示空 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:62-123。注意:头部注释说“高 6 位为区域、低 10 位为索引,每区只能 1000 个节点”,与实际 16/16 位域及 10240 上限不符——注释是旧版设计遗留 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:25-29。
2.2 CPathNode(32 字节)#
在 360/PS3 向量化路径下编译期断言 sizeof(CPathNode) == 32 且 16 字节对齐,以便单条 lvlx 指令解包坐标 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:374-397。字段:搜索用的 m_pNext/m_pPrevious 与 m_distanceToTarget(运行时,不序列化)、地址、街道名哈希、链接起始索引、XY 坐标,以及两个打包 u32 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:226-288、src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:354-370:
| 位域 | 含义 |
|---|---|
m_1: m_group(3) m_Offroad m_onPlayersRoad m_noBigVehicles m_cannotGoRight/Left m_slipLane m_indicateKeepLeft/Right m_specialFunction(5) m_coorsZ(16) | 洪水填充组、越野、玩家道路标记(人口用)、禁大车、转向限制、匝道、GPS 提示、特殊功能、Z |
m_2: m_noGps m_closeToCamera m_slipJunction m_alreadyFound m_switchedOffOriginal m_waterNode m_highwayOrLowBridge m_switchedOff m_qualifiesAsJunction m_speed(2) m_numLinks(5) m_inTunnel m_distanceHash(7) m_density(4) m_deadEndness(3) m_leftOnly | GPS 屏蔽、开关状态、水面、高速、路口、速度档(慢/正常/快/双倍)、链接数、隧道、7m 间距哈希、密度 0–15、死路程度 |
特殊功能枚举(停车位、加油站、行人过街、交通灯、让行、强制/伪路口、禁区、禁止生成车辆…)上限 31(5 位)src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:126-153。HasSpecialFunction_Driving() 把交通灯/让行等“普通交通用途”排除在外 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:335-344。
2.3 CPathNodeLink(8 字节)#
m_OtherNode + 一个打包 u32:GPS 双向、无车道时阻断、侧倾 m_Tilt(5) 与衰减、窄路、通向/来自死路(为 SPU 预计算)、中央宽度 m_Width(4,值 15 表示所有车道走中线的小巷)、不用于导航(并道/匝道连接段)、捷径、双向车道数(各 3 位)、距离(8) src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:407-501。车道宽 5.4m(窄路 4.0m),车道中心偏移由车道数与中央宽度推导 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:407-409、src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:444-486。
2.4 CPathRegion 与虚拟路口#
CPathRegion : pgBase 是一个可重定位资源:节点数组(车辆节点在前、行人节点在后)、链接数组、虚拟路口 CPathVirtualJunction(路口区域的高度栅格,用于 dummy 车在路口内的路面高度)、高度样本、atBinaryMap 路口映射 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:504-591。__DEV/RAGEBUILDER/资源编译器构建可从 XML 读写区域 src/dev_ng/rage/framework/src/fwvehicleai/pathfindtypes.h:554-562;离线构建器 CPathFindBuild : CPathFind 负责节点排序、合并、开放空间节点、距离哈希洪水填充与保存 src/dev_ng/game/vehicleAi/Pathfind_Build.h:22-49。
3. CPathFind:流式模块与查询#
3.1 作为流式模块#
CPathFind : strStreamingModule,全局实例 ThePaths src/dev_ng/game/vehicleAi/pathfind.h:215、src/dev_ng/game/vehicleAi/pathfind.h:1329。注册与生命周期:
| 时机 | 调用 | 证据 |
|---|---|---|
| 启动注册流式模块 | CPathFind::RegisterStreamingModule → AddModule(&ThePaths) | src/dev_ng/game/core/game.cpp:581、src/dev_ng/game/vehicleAi/pathfind.cpp:13873-13876 |
| 核心初始化 | CScene 中 ThePaths.Init(INIT_CORE);会话初始化经 CPathFindWrapper::Init | src/dev_ng/game/scene/scene.cpp:629、src/dev_ng/game/core/game.cpp:2325 |
| 不存在的区域 | 注册为 DEGENERATEPATHREGION 哑对象(同样处理“传家宝岛”区域,偏移 sm_iHeistsOffset = PATHFINDREGIONS) | src/dev_ng/game/vehicleAi/pathfind.cpp:13878-13900、src/dev_ng/game/vehicleAi/pathfind.cpp:126 |
| 放置 | PlaceResource → pgRscBuilder::PlaceStream → Load | src/dev_ng/game/vehicleAi/pathfind.cpp:337-353 |
| 装载 | 设置 apRegions[i],把每个节点的 m_distanceToTarget 置为 PF_VERYLARGENUMBER,并重放所有尚未撤销的脚本节点开关 | src/dev_ng/game/vehicleAi/pathfind.cpp:360-404 |
| 卸载 | Unload 并删除区域对象 | src/dev_ng/game/vehicleAi/pathfind.cpp:306-330 |
3.2 UpdateStreaming#
由 CStreaming 更新循环调用 src/dev_ng/game/streaming/streaming.cpp:783-784,每 512ms 才真正执行一次((time & ~511) != (prevTime & ~511)),或在强制时立即执行 src/dev_ng/game/vehicleAi/pathfind.cpp:12380-12384。步骤:清空待流送标记;bLoadAllRegions 时标记全部;否则以焦点实体(或玩家切换目标)为中心标记 STREAMING_PATH_NODES_DIST_PLAYER = 1765m 内的区域,保留 GPS 周期/起止异步搜索周围的区域(1765/150m),再遍历车辆池为 AI 车辆标记周围区域 src/dev_ng/game/vehicleAi/pathfind.cpp:12386-12470、src/dev_ng/game/vehicleAi/pathfind.h:50-52。另外脚本、游戏与地图可通过 AddNodesRequiredRegionThisFrame 声明每帧必需区域(地图 4、脚本 12、游戏 20 个槽)src/dev_ng/game/vehicleAi/pathfind.h:295-324、src/dev_ng/game/vehicleAi/pathfind.cpp:12218。切换到/离开传家宝岛地图时,会清除所有区域的必需标志并 StreamingRemove 主图与岛图的全部区域,再强制重载 src/dev_ng/game/vehicleAi/pathfind.cpp:12344-12378。
每帧 CScene::Update 中 ThePaths.Update() 仅调用 UpdateUsedNodes(加调试工具)src/dev_ng/game/scene/scene.cpp:825-826、src/dev_ng/game/vehicleAi/pathfind.cpp:613-635。
3.3 DoPathSearch:A*(从目标反向搜索)#
DoPathSearch 的参数包括起点坐标/节点、目标坐标、输出节点数组与请求数、截止距离、最大搜索距离、不逆行、避开节点、两栖/船、GPS 模式、捷径、忽略关闭节点、遵守交规、偏好目标节点列表、避高速/禁区/越野,以及输出每节点车道偏移与宽度 src/dev_ng/game/vehicleAi/pathfind.cpp:1023-1030。实现要点:
- 反向:先把目标节点放入 OPEN 集,直到弹出起点节点为止;每个节点的累计代价存在节点自身的
m_distanceToTarget中,结束后用aNodesToBeCleared(最多PF_MAXNUMNODES_INSEARCH = 5000)把访问过的节点复位src/dev_ng/game/vehicleAi/pathfind.cpp:1206-1228、src/dev_ng/game/vehicleAi/pathfind.cpp:985、src/dev_ng/game/vehicleAi/pathfind.h:1161。回溯时从起点沿“邻居距离 = 本节点距离 − 链接长度”的边走向目标,因此输出天然是从起点到目标的顺序src/dev_ng/game/vehicleAi/pathfind.cpp:1896。 - 桶式优先队列:OPEN 集是按“累计代价 + 启发值”取模
PF_HASHLISTENTRIES = 512的哈希桶链表;维护当前最小/最大估价,最小值所在桶即下一个扩展对象;当估价范围超过 512 时才需要逐个校验节点估价src/dev_ng/game/vehicleAi/pathfind.cpp:1247-1292、src/dev_ng/game/vehicleAi/pathfind.h:48。 - 启发函数:
0.9 × 欧氏距离(0.9 来自构建器中快速道路的距离系数,保证低估),注释比较了 Chebyshev 与对角近似并说明取舍src/dev_ng/game/vehicleAi/pathfind.cpp:987-1021。 - 保护:迭代超过 50000 次断言并跳出
src/dev_ng/game/vehicleAi/pathfind.cpp:1241-1245;__BANK记录最近 16 次搜索历史与耗时src/dev_ng/game/vehicleAi/pathfind.cpp:1034-1060、src/dev_ng/game/vehicleAi/pathfind.h:326-330。
AI 车辆不会一次性搜索全程:CPathNodeRouteSearchHelper 只请求 CAR_MAX_NUM_PATHNODES_STORED − 已保留节点数 个节点(最多 14),因此车辆是以“滚动窗口”方式持续重搜(推断,依据请求数与节点列表容量)src/dev_ng/game/task/System/TaskHelpers.cpp:2974-2984。区域未加载且允许等待时,搜索助手停留在 State_Searching src/dev_ng/game/task/System/TaskHelpers.cpp:2964-2970。
3.4 其他查询#
FindNodeClosestToCoors(带回调过滤版本)与按方向/车道等多种节点查询src/dev_ng/game/vehicleAi/pathfind.cpp:7434、src/dev_ng/game/vehicleAi/pathfind.cpp:7558。- 异步最近节点搜索:
StartAsyncGPSSearch把参数(含 GPS 禁用区)打包成sysTaskParameters,以sysTaskManager::Create(TASK_INTERFACE(PathfindNodeSearchSPU), ...)启动;PS3 额外把区域指针表作为只读 DMA 输入并给 180KB scratchsrc/dev_ng/game/vehicleAi/pathfind.cpp:7671-7707。注意PathfindNodeSearchJob.cpp的头注释写的是“Vehicle population SPU update”,与实际内容不符(复制遗留)src/dev_ng/game/vehicleAi/PathfindNodeSearchJob.cpp:1-2。 - 节点开关:脚本可在区域内关闭/恢复道路(
SwitchRoadsOffInArea),最多MAX_NUM_NODE_SWITCHES = 100条记录,任务结束时按脚本线程撤销src/dev_ng/game/vehicleAi/pathfind.cpp:10883、src/dev_ng/game/vehicleAi/pathfind.h:54-56、src/dev_ng/game/vehicleAi/pathfind.h:140-143。 FindStreetNameAtPosition仅在 PS4/PC/XB1 编译src/dev_ng/game/vehicleAi/pathfind.cpp:10581-10587。
4. CVehicleIntelligence#
4.1 组成#
CVehicleIntelligence 使用池(与车辆池同大小、按最大子类分配)src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:81,工厂按车型创建直升机/飞机子类 src/dev_ng/game/vehicleAi/VehicleIntelligenceFactory.cpp:20-32。主要成员:任务管理器 CVehicleTaskManager m_TaskManager src/dev_ng/game/vehicleAi/VehicleIntelligence.h:799;车辆/行人/物体扫描器;一组 CExpensiveProcess 分摊器(转向、刹车、变道、dummy 避让、跟车、导航网格视线、路口更新、警笛反应),把昂贵计算分散到不同帧 src/dev_ng/game/vehicleAi/VehicleIntelligence.h:373-384、src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:259-280;车辆事件组;“前方挡路车”;备用 follow route m_BackupFollowRoute(任务丢失时给 superdummy 用)src/dev_ng/game/vehicleAi/VehicleIntelligence.h:386-392。
4.2 Process 与收尾#
CVehicleIntelligence::Process src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:985-1126:
- 每帧都立即传播“身后车辆数”;非全量帧到此为止
src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:987-993。 - 重置每帧标志(警告行人、允许 dummy、时间片许可等——任务需在本次更新中重新声明是否允许时间片)
src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:995-1008。 - 坦克/曾被玩家拥有的飞行器在无人驾驶时、或需要为警笛让路时,强制其他车辆为其停车
src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1010-1015。 - 船只避让助手;路口更新由分摊器决定是否本帧执行
src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1022-1029。 - 网络克隆只更新附近实体列表与路口后返回(AI 在拥有者端运行)
src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1031-1042。 - 爆炸击飞的车在物理停止前禁止转 dummy;假乘员车任务丢失时重建默认任务;处理 dummy 标志
src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1044-1063。 - 若在播放“不使用 AI”的录像:失效缓存的节点列表/路线、标记避让脏、只处理事件与任务(让敞篷顶等仍工作);否则正常流程:预更新、路口、身后车、重置变量、附近实体、失效缓存、停滞计时、事件、
m_TaskManager.Processsrc/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1065-1107。 - 非 PS3 上把收尾排入
g_VehicleIntelligenceProcess延迟任务src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1109-1125。
收尾 Process_OnDeferredTaskCompletion 缓存当前任务的节点列表与 follow route(避免后续反复查询任务树),停放车请求时间片,并对 dummy 车做安全检查:若任务禁止 dummy、follow route 少于两个点(且物理激活)或约束剧变,则尝试转回 real;转不回且没有路线时停用物理 src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1128-1199。
5. 车辆任务#
5.1 任务参数与驾驶标志#
所有车辆任务派生自 CTaskVehicleMissionBase : CTask,持有 sVehicleMissionParams:目标实体或位置、到达距离、驾驶标志、巡航速度、最大巡航速度、目标障碍尺寸系数;默认驾驶模式 DMode_StopForCars src/dev_ng/game/vehicleAi/task/TaskVehicleMissionBase.h:28-70、src/dev_ng/game/vehicleAi/task/TaskVehicleMissionBase.h:238-296。任务可声明网络同步/可迁移并提供序列化器 src/dev_ng/game/vehicleAi/task/TaskVehicleMissionBase.h:320-330。
DrivingFlags 是一个 32 位位集(停车让车/让人、绕行、走对向车道、倒车、禁区回避、调整路速、捷径、变道、使用关闭节点、偏好导航网格、飞机滑行、强制直线、路口拉线、避高速、完成后不终止等),并组合出脚本可用的驾驶模式;注释要求同步修改脚本头 commands_vehicle.sch src/dev_ng/game/vehicleAi/VehMission.h:93-151。旧式任务类型 VehMissionType 与临时动作 VehTempActType 仍作为脚本/网络使用的枚举存在 src/dev_ng/game/vehicleAi/VehMission.h:5-91。
5.2 任务族#
| 类别 | 代表类 | 证据 |
|---|---|---|
| 巡航/前往(核心) | CTaskVehicleCruiseNew、CTaskVehicleGoToAutomobileNew、CTaskVehicleFlee | src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:26、src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:178、src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:452 |
| 底层驾驶 | CTaskVehicleGoToPointWithAvoidanceAutomobile、CTaskVehicleGoToPointAutomobile、CTaskVehicleGoToNavmesh | src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:80、src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:552、src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:603 |
| 长距离 | CTaskVehicleGotoLongRange(分段请求节点区域后再前往中间目标,时间片帧也持续请求) | src/dev_ng/game/vehicleAi/task/TaskVehicleGoToLongRange.h:6-67 |
| 飞行/水上/潜艇 | 直升机/飞机/船/潜艇前往、降落、悬停、坠毁、空中逃离、追机 | src/dev_ng/game/vehicleAi/task/TaskVehicleGoToHelicopter.h:20、src/dev_ng/game/vehicleAi/task/TaskVehicleGoToPlane.h:20、src/dev_ng/game/vehicleAi/task/TaskVehicleGotoBoat.h:14、src/dev_ng/game/vehicleAi/task/TaskVehicleGoToSubmarine.h:17、src/dev_ng/game/vehicleAi/task/TaskVehicleFlying.h:25-234 |
| 战斗/追逐/执法 | 攻击、坦克攻击、追击、冲撞、阻挡、包围、护航、并行、警察行为(车/直升机/船)、直升机护卫 | src/dev_ng/game/vehicleAi/task/TaskVehicleAttack.h:23、src/dev_ng/game/vehicleAi/task/TaskVehiclePursue.h:23、src/dev_ng/game/vehicleAi/task/TaskVehicleRam.h:17、src/dev_ng/game/vehicleAi/task/TaskVehicleBlock.h:15、src/dev_ng/game/vehicleAi/task/TaskVehicleEscort.h:24、src/dev_ng/game/vehicleAi/task/TaskVehiclePoliceBehaviour.h:21-145 |
| 停车/停止 | 停车、靠边、乘客下车、新停车逻辑、对警笛反应、三点掉头 | src/dev_ng/game/vehicleAi/task/TaskVehiclePark.h:24-428、src/dev_ng/game/vehicleAi/task/TaskVehicleThreePointTurn.h:24 |
| 临时动作 | 等待/倒车/刹车/手刹/转向/前进/急转/飞向/迎头碰撞/助推/沿点路径/烧胎/轰油门/上浮 | src/dev_ng/game/vehicleAi/task/TaskVehicleTempAction.h:25-817 |
| 录像 | CTaskVehicleFollowRecording、CTaskVehicleFollowWaypointRecording | src/dev_ng/game/vehicleAi/task/TaskVehicleFollowRecording.h:21、src/dev_ng/game/vehicleAi/task/TaskVehicleFollowRecording.h:65 |
| 无人/死亡司机/爆胎/打滑 | CTaskVehicleNoDriver、CTaskVehicleDeadDriver、CTaskVehicleShotTire、CTaskVehicleSpinOut | src/dev_ng/game/vehicleAi/task/TaskVehiclePlayer.h:497、src/dev_ng/game/vehicleAi/task/TaskVehicleDeadDriver.h:22、src/dev_ng/game/vehicleAi/task/TaskVehicleShotTire.h:13、src/dev_ng/game/vehicleAi/task/TaskVehicleSpinOut.h:17 |
| 动画(副树) | 车辆动画、敞篷顶、变形为潜艇 | src/dev_ng/game/vehicleAi/task/TaskVehicleAnimation.h:23-190 |
| 玩家驾驶 | CTaskVehiclePlayerDrive 及各车型子类(输入 → CVehControls) | src/dev_ng/game/vehicleAi/task/TaskVehiclePlayer.h:33-477 |
TaskVehicleGoToAutomobile.h 中的 CTaskVehicleGoToRacing 已被整段注释掉 src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:32-50。
5.3 CTaskVehicleCruiseNew#
状态:FindRoute → CalculatingRoute → Cruise,以及 StopForJunction、WaitBeforeMovingAgain、GoToStraightLine、GoToNavmesh、GetToRoadUsingNavmesh、Burnout、RevEngine、PauseForUnloadedNodes、Stop;运行标志记录“找不到路线 / 强制重算 / 无法上路” src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:181-204。它暴露节点列表、follow route 与路线搜索助手,支持模板路口的路径修正、变道请求 src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:239-258。网络同步时只序列化“未来节点”压缩表示:第一个节点地址 32 位 + 两个“链接 5 位/车道 3 位”字节 src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:208-282。CTaskVehicleGoToAutomobileNew 继承巡航任务实现定点前往 src/dev_ng/game/vehicleAi/task/TaskVehicleCruise.h:452-455。
5.4 避障与转向:CTaskVehicleGoToPointWithAvoidanceAutomobile#
这是把“目标点”转换为控制输入的底层任务,状态为 GoToPoint、ThreePointTurn、WaitForTraffic、WaitForPed、TemporarilyBrake、Swerve src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:168-177。关键机制:
- 障碍收集:车辆、行人、物体、道路边缘四类(
eObstructionType),分别由FindVehicleObstructions/FindPedObstructions/FindObjectObstructions/FindRoadEdgesUsingFollowRoute填充AvoidanceTaskObstructionDatasrc/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:229-275、src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:371-377。 - 方向打分:对一组候选方向做线段测试(对车辆、圆柱障碍、follow route 道路边界),
ScoreAvoidanceDirections选出最优方向src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:363-417。 - 限速:
FindMaximumSpeedForThisCarInTraffic与按扇区列表为行人/门/其他车减速src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:319-347;执法车辆/行人的障碍单独识别src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:330-331。 - 可调参数:跟车距离/速度倍率、行人闪避的速度/距离阈值、危险驾驶判定等
src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:97-123。 - 多线程:主计算放在
GoToPointWithAvoidance_OnDeferredTask,superdummy 运动放在..._OnDeferredTask_ProcessSuperDummy,两个阶段由VehicleAvoidanceTask分两次并行批处理,最后在主线程OnDeferredTaskCompletion收尾src/dev_ng/game/vehicleAi/task/TaskVehicleGoToAutomobile.h:286-288、src/dev_ng/game/vehicleAi/task/DeferredTasks.cpp:208-252。第一批运行期间物理层仍处于“仅主线程更新”状态,第二批(会移动 superdummy)之前才关闭该标志src/dev_ng/game/vehicleAi/task/DeferredTasks.cpp:221-228。
驾驶员个性 CDriverPersonality 提供能力、激进度、最高巡航速度、绿灯起步延迟、是否闯黄灯/停车标志、跟车距离、变道/打灯习惯等静态查询 src/dev_ng/game/vehicleAi/driverpersonality.h:19-43。
6. 节点列表、路线搜索与 follow route#
6.1 CVehicleNodeList#
固定 CAR_MAX_NUM_PATHNODES_STORED = 12 + 2 个条目:前 2 个是“旧节点”(只为让虚拟路面不跳变而保留),其后是当前与未来节点;每条目含节点地址、链接索引、车道索引,m_targetNodeIndex 标记当前目标 src/dev_ng/game/vehicleAi/VehicleNodeList.h:16-56、src/dev_ng/game/vehicleAi/VehicleNodeList.h:60-140。提供移位、求链接/车道、接入路网 JoinToRoadSystem(默认 60m 拒绝距离)等操作 src/dev_ng/game/vehicleAi/VehicleNodeList.h:105-124、src/dev_ng/game/vehicleAi/pathfind.h:58。
6.2 CPathNodeRouteSearchHelper#
一个 CTaskHelperFSM:Start → FindStartNodesInDirection / FindStartNodesAnyDirection → GenerateWanderRoute 或 Searching → ValidRoute / NoRoute src/dev_ng/game/task/System/TaskHelpers.h:934-956。“漫游”路线由 GenerateWanderRoute_OnUpdate 从已接入路网的节点逐步向前选择后续节点(会参考玩家所在道路,避免车辆在玩家附近打转),不调用 A* src/dev_ng/game/task/System/TaskHelpers.cpp:4869-4930;该文件中唯一的 DoPathSearch 调用位于定点搜索的 Searching 状态(3.3)src/dev_ng/game/task/System/TaskHelpers.cpp:2903、src/dev_ng/game/task/System/TaskHelpers.cpp:2974。
6.3 CVehicleFollowRouteHelper 与 CRoutePoint#
follow route 是节点列表的几何化:最多 MAX_ROUTE_SIZE = 14 个 CRoutePoint,每点含位置+速度(Vec4V)、中央/车道宽度、指定车道、两侧路拱与衰减、两侧车道数、单行道/忽略导航/路口/左转专用/高速/匝道标志、车道中心偏移与节点地址(塞进向量分量)src/dev_ng/game/task/System/TaskHelpers.h:1079-1169、src/dev_ng/game/task/System/TaskHelpers.h:1177-1200。构造来源有四种:节点列表(可选拉线与变道助手)、航点录像、导航网格路线、路点数组 src/dev_ng/game/task/System/TaskHelpers.h:1214-1219。
| 用途 | 函数 | 证据 |
|---|---|---|
| 目标点与速度 | FindTargetCoorsAndSpeed(新旧两版实现与“isolated”纯函数版本) | src/dev_ng/game/task/System/TaskHelpers.h:1237-1240、src/dev_ng/game/task/System/TaskHelpers.h:1312-1327 |
| superdummy 运动 | ProcessSuperDummy、CalculatePositionAndOrientationOnVirtualRoad、UpdateTimeslicedInterpolationTarget | src/dev_ng/game/task/System/TaskHelpers.h:1227-1233、src/dev_ng/game/task/System/TaskHelpers.cpp:10299 |
| dummy 虚拟路面 | CVirtualRoad::HelperCreateRouteInfoFromFollowRouteAndCenterPos | src/dev_ng/game/Vehicles/Automobile.cpp:8408-8432 |
| 物理约束许可 | SetAllowUseForPhysicalConstraint | src/dev_ng/game/task/System/TaskHelpers.h:1224-1225 |
速度在构造时预计算(CalculateDesiredSpeeds),节点的速度档通过 FindSpeedMultiplierWithSpeedFromNodes 映射为 0.5/1.0/1.6/2.2 倍 src/dev_ng/game/task/System/TaskHelpers.h:1218-1219、src/dev_ng/game/vehicleAi/VehicleIntelligence.h:189-200。
7. 路口与交通灯#
7.1 CJunctions / CJunction#
| 常量 | 值 | 证据 |
|---|---|---|
同时活跃路口 JUNCTIONS_MAX_NUMBER | 360/PS3 60,否则 128 | src/dev_ng/game/game_config.h:55 |
每路口车辆 MAX_VEHICLES_AT_JUNCTION | 64 / 128 | src/dev_ng/game/game_config.h:52 |
| 模板数 / 入口 / 交通灯位置 / 路口节点 | 150 / 16 / 8 / 8 | src/dev_ng/game/vehicleAi/junctions.h:30-34 |
| 每路口相位 / 交通灯实体 / 铁路栏杆 / 铁轨 | 8 / 12 / 8 / 4 | src/dev_ng/game/vehicleAi/junctions.h:245-263 |
(junctions.psc 注释中仍写着 JUNCTIONS_MAX_NUMBER 56,与 game_config.h 不一致,以代码为准 src/dev_ng/game/vehicleAi/junctions.psc:4-10。)
CJunctions::Update(注册在 Game Logic 组 src/dev_ng/game/core/game.cpp:2842):以玩家位置加上其地面车辆速度为中心扫描并实例化路口(避免高速接近时交通灯晚出现);联机时用网络同步时间计算时间步;启用时间片时每帧只完整更新 ceil(有车路口数 / 周期) 个路口,长时间未更新的路口也会被补更新 src/dev_ng/game/vehicleAi/junctions.cpp:3874-3960。车辆通过 AddVehicleToJunction/RemoveVehicleFromJunction 登记,路口据此判断冲突路线(VehicleRouteClashesWithOtherCarOnJunction)src/dev_ng/game/vehicleAi/junctions.h:555-557、src/dev_ng/game/vehicleAi/junctions.cpp:1073。路口还管理铁路道口(栏杆升降、道口灯脉冲、扫描接近的火车);按注释与代码,火车接近或栏杆未完全抬起时模板路口对所有入口返回 STOP src/dev_ng/game/vehicleAi/junctions.cpp:2395-2440、src/dev_ng/game/vehicleAi/junctions.cpp:2499-2528、src/dev_ng/game/vehicleAi/junctions.cpp:904-911。
模板数据优先从 JUNCTION_TEMPLATES_PSO_FILE(junctions.pso,忽略校验和)加载,否则读 junctions.xml;加载后补齐到 150 个条目 src/dev_ng/game/vehicleAi/junctions.cpp:4641-4690。模板结构:标志、节点/入口/相位/交通灯位置数、搜索距离、相位偏移、包围盒、节点位置、入口(相位、停止距离、朝向、红灯右转、车道限制、左转滤波相位)、相位时序、交通灯位置;另有“自动路口调整”(位置、周期偏移、周期长度)src/dev_ng/game/vehicleAi/junctions.psc:12-71。__DEV 下有路口编辑器 src/dev_ng/game/vehicleAi/junctions.h:14、src/dev_ng/game/vehicleAi/JunctionEditor.h:6-11。
7.2 两种相位逻辑#
- 模板路口(
m_iTemplateIndex != -1):CJunction::Update在本路口的m_LightTiming相位间轮转;故障时随机跳相位;单机模式下可跳过无人的行人相位,并按该相位入口的排队车辆数调整时长(空 ×0.5、≤3 辆 ×1.0、≥8 辆 ×2.0、≥14 辆 ×2.5),联机时不做自适应以保持各机一致src/dev_ng/game/vehicleAi/junctions.cpp:318-420、src/dev_ng/game/vehicleAi/junctions.cpp:122-128。GetTrafficLightCommand返回 STOP/AMBER/GO/左右转滤波/行人等命令src/dev_ng/game/vehicleAi/junctions.cpp:890-922、src/dev_ng/game/vehicleAi/junctions.h:38-49。 - 节点交通灯(
SPECIAL_TRAFFIC_LIGHT节点):CTrafficLights::CalculateNodeLightCycle根据进入路口方向的主轴(|x|>|y| → 周期 1,否则周期 2)分配相位src/dev_ng/game/control/trafficlights.cpp:196-269;灯色完全由网络同步时间(加路口自动调整的偏移/缩放)对周期长度取模得到:周期 = 长绿 10s + 短绿 10s + 2×黄 2.5s = 25s,带行人相位时再加 15s 行人与一个黄灯 = 42.5ssrc/dev_ng/game/control/trafficlights.cpp:453-503、src/dev_ng/game/control/trafficlights.h:80-85。注释中的时间表自称“THIS IS WRONG”src/dev_ng/game/control/trafficlights.cpp:463-468。
ShouldCarStopForLightNode 的判定:忽略本路口的出口灯与不属于当前路口的灯;红灯必停,黄灯由 CDriverPersonality::RunsAmberLights 决定;允许已越线车辆(不超过 1 个车长,大车 0.5 个)继续通过;检查过一组灯后不再检查下一组,以免连续两组灯卡住车辆 src/dev_ng/game/control/trafficlights.cpp:294-451。
7.3 CTrafficLights 的其他职责#
- 每帧仅更新“交通灯地面光照亮度”:20 点后全亮、19–20 点渐亮、6 点后熄灭、5–6 点渐暗,并取湿度/雾/雨的最大值
src/dev_ng/game/control/trafficlights.cpp:154-188。 - 交通灯模型(
MODEL_ATTRIBUTE_IS_TRAFFIC_LIGHT)实体通过扩展TrafficLightInfos(池大小来自配置)记录所属路口、灯索引、入口/车道链接(最多 8)、已损坏灯色位掩码与缓存的骨骼矩阵src/dev_ng/game/control/trafficlights.h:175-330、src/dev_ng/game/control/trafficlights.cpp:63;RenderLights/RenderPedLights负责灯与 corona 的渲染src/dev_ng/game/control/trafficlights.h:145-150。
8. 车辆录像:CVehicleRecordingMgr#
| 方面 | 实现 | 证据 |
|---|---|---|
| 数据格式 | CVehicleRecording : pgBase 是 CVehicleStateEachFrame 数组:时间戳、速度(s16,最高 120 m/s)、矩阵 A/B 轴(s8)、转向/油门/刹车/手刹(s8)、位置(float) | src/dev_ng/rage/framework/src/fwcontrol/record.h:4-54、src/dev_ng/rage/framework/src/fwcontrol/record.h:67-100 |
| 容量 | 同时录制 / 回放各 24 辆;录制缓冲 480000 字节(约 40 分钟),每 125ms 记录一帧,每 10s 刷盘 | src/dev_ng/rage/framework/src/fwcontrol/record.h:56-57、src/dev_ng/game/control/record.h:37-53 |
| 流式 | 录像文件作为流式模块注册(启动时 RegisterStreamingModule),CVehicleRecordingStreaming 管理引用计数与 Place/Remove | src/dev_ng/game/core/game.cpp:579、src/dev_ng/game/control/record.h:63-105 |
| 回放 | StartPlaybackRecordedCar(车, 索引, 是否用 AI, 速度, 驾驶标志, 循环, …, 标志, AI 恢复延迟);每槽维护附加旋转、局部/全局偏移、运行时间、速度、暂停、AI 模式等 | src/dev_ng/game/control/record.h:241、src/dev_ng/game/control/record.h:358-381 |
| 推进 | RetrieveDataForThisFrame 对 24 个槽逐个 UpdatePlaybackForVehicleRecording;sm_bUpdateWithPhysics 时在每个物理时间片推进(时间步按时间片数均分,仍以游戏毫秒计时以免与脚本计时漂移),否则在 CGameWorld::Process 物理之后推进 | src/dev_ng/game/control/record.cpp:1849-1882、src/dev_ng/game/physics/physics.cpp:1383-1388、src/dev_ng/game/scene/world/GameWorld.cpp:2094-2105 |
| 驱动车辆 | 插值帧间状态后 SetMatrix + HandleRecordingTeleport,设置线速度与角速度 | src/dev_ng/game/control/record.cpp:2312-2383 |
| AI 混合 | ChangeCarPlaybackToUseAI 让录像车改由 AI 驾驶并可在之后恢复全录像;FinishAiUpdate 与 CVehicleIntelligence::Process 对“不使用 AI 的录像”走简化路径 | src/dev_ng/game/control/record.cpp:1655、src/dev_ng/game/control/record.cpp:2790、src/dev_ng/game/Vehicles/Vehicle.cpp:29876-29880、src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1065-1081 |
| 物理交互 | 录像车可在物理层非激活状态回放;ProcessPostPhysics 处理切换 AI 与非激活 | src/dev_ng/game/Vehicles/Vehicle.cpp:2079-2090、src/dev_ng/game/Vehicles/Automobile.cpp:3531-3533 |
| 录制 | 非 __FINAL 构建每帧 SaveDataForThisFrame | src/dev_ng/game/scene/world/GameWorld.cpp:2096-2098 |
9. 航点录像与路线池#
fwWaypointRecordingRoute : pgBase:每个航点 = 位置 + 打包(标志 16 位、朝向 8 位、移动混合比 8 位)+ 左右可用空间;标志含跳跃、着陆、滑雪翻转、下落、不可打断、出水、车辆、施加跳跃力;最多 512 个航点src/dev_ng/rage/framework/src/fwcontrol/WaypointRecordingRoute.h:12-50、src/dev_ng/rage/framework/src/fwcontrol/WaypointRecordingRoute.h:88-107。CWaypointRecording作为流式模块(CWaypointRecordingStreamingInterface)供脚本请求/引用计数,__BANK下可录制与编辑(步行、滑雪、车内分别有采样间距参数)src/dev_ng/game/control/WaypointRecording.h:56-188、src/dev_ng/game/core/game.cpp:578;游戏版CWaypointRecordingRoute只在__BANK下增加编辑函数src/dev_ng/game/control/WaypointRecordingRoute.h:1-20。车辆跟随航点录像时由CVehicleFollowRouteHelper::ConstructFromWaypointRecording转成 follow routesrc/dev_ng/game/task/System/TaskHelpers.h:1215。Route.h的CPointRoute(最多 8 点,池 40、spillover 0.66)与CPatrolRoute(每点附带动画描述,池 6)是 ped 路线的小型池化容器src/dev_ng/game/control/Route.h:93-118、src/dev_ng/game/control/Route.h:297-328、src/dev_ng/game/control/Route.cpp:4-5。
10. GPS:CGps#
GPS 有 3 个槽:航点、雷达标记、离散路线(后者不播报);雷达标记槽同时承载赛道、多点航点与自定义路线 src/dev_ng/game/vehicleAi/pathfind.h:40-44、src/dev_ng/game/control/gps.h:26-29、src/dev_ng/game/control/gps.cpp:2426-2427。每槽存储节点坐标(因为路网节点可能被流出)、地址、节点信息与到终点距离,容量来自配置池 CGpsNumNodesStored src/dev_ng/game/control/gps.h:174-177、src/dev_ng/game/control/gps.cpp:2322。
| 方面 | 实现 | 证据 |
|---|---|---|
| 状态机 | OFF;计算中(普通/静默/赛道/多点);工作中(普通/赛道/多点/自定义) | src/dev_ng/game/control/gps.h:81-98 |
| 计算 | 向 ThePaths 申请包围起终点的节点区域(MakeRequestForNodesToBeLoaded),区域就绪且本帧异步搜索未被占用时调用 GenerateRoutePointsForGps(..., async=true);返回负值表示异步搜索刚启动 | src/dev_ng/game/control/gps.cpp:391-468 |
| GPS 标志 | 忽略单行、遵守交规、避高速、不平移路线、自定义接近距离、避越野、忽略终点 Z 等 | src/dev_ng/game/vehicleAi/pathfind.h:153-163 |
| 推进 | UpdateRoute:按最近线段 ShiftRoute 截掉已走过的部分,并定期重绘 | src/dev_ng/game/control/gps.cpp:941-986 |
| 指令与语音 | CalcRouteInstruction 把路网方向转换为左转/右转/靠左/靠右/直行/掉头等指令并播报 | src/dev_ng/game/control/gps.h:100-114、src/dev_ng/game/control/gps.cpp:1745-1794 |
| 每帧 | CGps::Update 更新各槽、释放未使用的异步搜索槽 | src/dev_ng/game/control/gps.cpp:2367-2441、src/dev_ng/game/core/game.cpp:2837 |
11. 其他车辆 AI 组件#
| 组件 | 作用 | 证据 |
|---|---|---|
CFlyingVehicleAvoidanceManager | 飞机/直升机之间的转向避让(每帧在人口组更新) | src/dev_ng/game/vehicleAi/FlyingVehicleAvoidance.h:15-77、src/dev_ng/game/core/game.cpp:2793 |
CRoadSpeedZone | 地图上让车辆减速的区域(最高速度) | src/dev_ng/game/vehicleAi/roadspeedzone.h:1-31 |
CPathZone / CPathZoneMapping | 最多 4 个路径区域及其互相映射(MAX_NUM_PATHZONES = 4) | src/dev_ng/game/vehicleAi/pathzones.h:10-60 |
VehicleNavigationHelper | 不用导航网格/路网时绕地形与物体导航的静态检查 | src/dev_ng/game/vehicleAi/VehicleNavigationHelper.h:10-14 |
racingline.* | 赛车线(TDeque 节点容器等) | src/dev_ng/game/vehicleAi/racingline.h:1-30 |
12. 线程与平台差异#
| 条件 | 影响 | 证据 |
|---|---|---|
!__PS3 | CVehicleIntelligence 收尾与车辆插值走延迟多线程任务 | src/dev_ng/game/vehicleAi/VehicleIntelligence.cpp:1109-1125 |
| 延迟任务期间 | 打开 fwRegdRef/事件/环境组/空间数组锁,联机时允许其他线程访问网络管理器,禁止任务删除 | src/dev_ng/game/vehicleAi/task/DeferredTasks.cpp:140-154 |
__PS3 | 异步最近节点搜索作为 SPU 任务运行(区域指针表 DMA、180KB scratch) | src/dev_ng/game/vehicleAi/pathfind.cpp:7684-7703 |
XENON_OR_PS3 | 路口/交通灯/生成链接容量减小 | src/dev_ng/game/game_config.h:51-55 |
RSG_ORBIS || RSG_PC || RSG_DURANGO | FindStreetNameAtPosition | src/dev_ng/game/vehicleAi/pathfind.cpp:10581-10587 |
__BANK / __DEV | 路径搜索历史、路网调试绘制(PATHSEARCHDRAW)、路口编辑器、航点录制 | src/dev_ng/game/vehicleAi/pathfind.h:326-330、src/dev_ng/game/vehicleAi/pathfind.cpp:79、src/dev_ng/game/vehicleAi/junctions.h:14、src/dev_ng/game/scene/world/GameWorld.cpp:2107-2110 |
13. 约束与边界行为#
- 节点指针只在区域加载时有效:
FindNodePointer断言区域已加载;安全版本在空地址、区域未加载或索引越界时返回NULLsrc/dev_ng/game/vehicleAi/pathfind.h:798-845。CVehicleNodeList::GetPathNode同样检查区域是否加载src/dev_ng/game/vehicleAi/VehicleNodeList.h:64-71。GPS 因此单独缓存坐标。 - 搜索状态写在共享节点上:
DoPathSearch把临时代价写入CPathNode::m_distanceToTarget并依赖“清理列表”复位,所以它不是可重入的,必须在主线程串行调用(推断,依据实现方式;异步 GPS 搜索使用独立的 SPU/任务版本)src/dev_ng/game/vehicleAi/pathfind.cpp:1206-1228。 - 网络:克隆车辆不运行任务 AI(4.2);交通灯与路口时间基于网络同步时间,模板路口在联机时不自适应
src/dev_ng/game/control/trafficlights.cpp:453-461、src/dev_ng/game/vehicleAi/junctions.cpp:3910-3923。 - dummy 安全阀:没有 follow route 的 dummy 车会被强制转回 real 或停用物理(4.2)。
14. 未决问题与证据不足#
- 未找到路网区域资源(
nodes*.ynd)与junctions.xml/pso数据本体,无法给出具体节点数量或模板内容。 TaskVehicleGoToAutomobile.cpp(约 49 万字节)与TaskVehicleCruise.cpp的完整控制律(转向 PID、刹车距离曲线、变道条件)只按结构描述;CVehPIDController的使用点未追踪。GenerateRoutePointsForGps的异步执行细节、PathfindNodeSearchJob.cpp中CPathFindGPSSpu的实现未展开。CJunction::Deploy(模板绑定与入口推断)与ScanAndInstanceJunctionsNearOrigin的扫描半径未展开。