物理集成、空间探测、破坏与布料
范围:physics/、cloth/,连接 scene/Physical、RAGE Physics/Fragment/Verlet。总入口:Summary。
1. 游戏层负责什么#
CPhysics 组织物理世界与游戏实体的时序,游戏 archetype、instance、material、碰撞记录和破坏规则将 GTA 语义接入 RAGE。底层碰撞检测和求解器的主要实现位于引擎,不能把 game/physics 当作完整物理引擎。
本层同时包含 WorldProbe、浮力、绳索、ragdoll constraints、破碎和形变。它们与游戏玩法强耦合:枪弹与相机要做空间查询,车辆要处理轮地作用,NPC 需要胶囊/布娃娃切换,爆炸需要冲量与碎片。
2. 物理时间片与更新边界#
CPhysics::Update 从游戏时步计算模拟时步,并在 ms_NumTimeSlices 循环中调用 PreSimUpdate、SimUpdate、PostSimUpdate。帧前还有实体 pre-physics 更新,后面继续 fragment、Verlet、rope 等流程。
图只概括职责顺序;rope 有不同 update order,部分工作可穿插于切片内,不能把图当作所有平台精确执行表。源码未在此证明一个适用于全部配置的固定 60 Hz,本文不附会固定频率。
在游戏回调前后,代码临时设置 SetOnlyMainThreadIsUpdatingPhysics(true/false)。注释说明这些区段由主线程更新,底层求解没有同时进行,可减少锁开销。这个约束只适用于明确的区段,不能推广成整个物理系统没有并行。
3. 延迟结构更新与对象生命周期#
接口包含 CommitDeferredOctreeUpdates、ProcessDeferredCompositeBvhUpdates、WaitForVerletTasks、manifold 处理和 warp instance。空间索引、碰撞缓存、游戏实体变换与异步工作不是自动同步的同一数据。
传送、删除、附件变更或修改 bound 时,需要遵循既定提交和清理路径。直接改游戏矩阵可能留下旧的物理空间索引;在异步探测使用实体期间删除对象则必须遵守引用/结果协议。这些是接口结构揭示的维护条件,不是本次确认的缺陷。
物理也有 UpdateStreaming、LoadAboutPosition 和 mover collision 范围控制。渲染可见并不代表远处碰撞资源已经就绪;高速移动和瞬移应同时考虑视觉、导航与碰撞预加载。
4. WorldProbe 的描述符与结果#
worldprobe.h 是聚合入口,引入 probe、sphere、capsule、batch、bound、bounding box 描述以及 shape test results。调用方用描述符声明查询体、范围和过滤,得到统一结果格式。
这种封装使相机避障、武器命中、落点检查等共享底层查询能力,同时保留各自过滤策略。查询形状不是可互换细节:点射线命中与胶囊扫掠代表不同体积;过滤掉自身、附件或玻璃也会改变玩法结果。
shape test manager、task 和 batch 文件体现调度/批处理分工。具体调用是同步还是异步必须看相应接口与描述符,不能仅凭使用 WorldProbe 便断言所有查询都异步。结果的实体指针、材料、接触点与法线也需要在有效生命周期内消费。
5. 材料、破坏和形变#
gtaMaterial、material manager 和 .psc 连接碰撞表面与游戏属性;Breakable、Deformable、CollisionRecords 把物理结果转换为可持久的破坏状态。玻璃有 BreakGlass 与 update 接口,并与 网络玻璃同步 交叉。
车辆形变还存在 GPU_DAMAGE_WRITE_ENABLED 条件下的排队/处理接口。它证明某些配置有 GPU 损伤写入协作路径,不代表当前所有平台都在 GPU 上完成全部车辆物理。阅读时必须把形变表现、结构破坏、碰撞响应和生命伤害分开。
NaturalMotion/ragdoll 的游戏任务位于角色任务体系,RagdollConstraints 提供相关物理约束;游戏 AI、动画和物理谁在控制某一帧,需要沿任务状态确认。
6. 布料与绳索#
cloth/ 包含 particles、springs、contacts、constraints、constraint graph、updater、archetype 与 RAGE interface。该分层将共享结构、运行粒子状态、约束关系和引擎物理实例分开。
CClothMgr 公开 solver 最大迭代数和容差,并管理 Add/Remove;头文件定义 64 cloth、8 archetype 的局部数组容量。目录同时还有 CClothRageMgr,底层也有 cloth manager,所以这些常量不能被当作全游戏全部布料的统一硬上限。
管理器的旧 Update() 声明被注释,实际通过 updater/interface 和物理调度衔接;只按类名寻找一个独立每帧更新会遗漏真实入口。迭代数和容差在质量、收敛与成本之间折中,不能在没有测试场景时给出普遍最优值。
Rope 与 Verlet 有独立的更新顺序和等待点。它们可能依附移动实体,约束锚点更新应与实体/骨骼阶段匹配;回收对象之前也要处理关联约束。
7. 诊断与证据#
静态检查可按“游戏实体 → 物理 instance → bound/material → 空间索引 → 模拟/查询 → 回调 → 游戏反馈”定位。碰撞异常不一定是窄相求交算法,可能来自资源、过滤、阶段或旧变换。运行评估应分别记录活动体、接触对、时间片、查询数和约束迭代;本文未编译或执行物理测试。
8. 源码依据#
| 源码 | 重点 |
|---|---|
| physics.h | 阶段、deferred 更新、streaming、GPU 条件接口 |
| physics.cpp | 2190 行起 Update;2290 行附近 time slices |
| worldprobe.h | 描述符与结果聚合 |
| shapetest.h | 查询生命周期入口 |
| ClothMgr.h | 局部容量、solver 参数、管理接口 |
| ClothUpdater.h | 布料计算组织 |