UE 的载具物理从 PhysX Vehicle 迁到 Chaos 之后,架构反而变清爽了:没有独立载具求解器,载具是套在刚体求解器上的一组约束和回调。这篇按模块拆开讲——控制器怎么把输入翻译成力、悬挂的射线模型怎么工作、轮胎摩擦曲线的形状意味着什么,最后落到联机这个老大难。
模块全景
四层结构,依赖单向向下:
ChaosVehicles(核心):载具物理本体,无引擎依赖,可独立测试;ChaosVehiclesEngine:传动模型(引擎扭矩曲线、变速箱、差速器);ChaosVehicle插件 +VehicleSystem运行时模块:UE 集成层,UChaosWheeledVehicleMovementComponent在这里;- 项目层:Pawn + MovementComponent 的配置资产(
UWheeledVehicleMovementComponent序列化的一堆参数)。
载具刚体本体是普通 Chaos 刚体——FPBDRigidsSolver 里的一个粒子,享受岛管理、休眠、异步物理的一切机制。载具的特殊性全在 ChaosVehicleManager:每帧求解器回调的钩子(FChaosVehicleManagerCallback)里,载具按固定顺序更新自己管理的轮子。
悬挂:射线模型的物理含义
Chaos 悬挂的基础模型是一条射线:每个轮子从悬挂硬点沿车底法线向下打一条射线,长度 = Suspension Max Raise + Max Drop。射线命中地面时,悬挂被压缩量 $x$ 由弹簧方程给出悬挂力:
$$F_{spring} = k \cdot x$$
$k$ 就是 Suspension Natural Frequency 的平方乘以簧载质量分配($k = m_{ sprung }(2\pi f)^2$,频率 $f$ 在组件里配)。阻尼项 $F_{damp} = c \cdot \dot{x}$,Damping Ratio 配的就是 $c$ 与临界阻尼 $c_{crit} = 2\sqrt{k m}$ 的比值——0.7 附近颠簸路不弹跳,1 以上过硬,0.3 以下过船。这组参数是载具手感的第一层,单位有物理意义,不是手感滑条。
悬挂力施加在硬点、方向沿悬挂轴线——所以侧倾中心、抗点头几何这类底盘工程概念,在 Chaos 里只能用硬点布置近似,没有多连杆模型。
轮胎:摩擦圆和滑移率
轮胎纵向力由滑移率(slip ratio)查表得到:
$$\sigma = \frac{\omega R - v}{\max(\lvert v \rvert, \epsilon)}$$
$\omega$ 轮速、$R$ 半径、$v$ 接地点纵向速度。Tire Friction 曲线横轴是 $\sigma$,纵轴是纵向力系数,形状决定驱动特性:峰值前的斜率决定起步响应,峰值后下降段($\sigma$ 超过 0.15 左右力反而降)是轮胎打滑的物理来源——大脚油门打滑不是"抓地力不够"的朴素逻辑,是工作点滑过了峰值。 Chaos 的默认曲线把这个峰做得很窄,所以默认参数的车一给油就漂,调宽峰值平台是载具手感的第二层。
横向力走摩擦圆组合:纵向力吃掉一部分附着力,横向可用上限按 $\sqrt{F_x^2 + F_y^2} \leq \mu F_z$ 收缩。ChaosVehicles 里 FTireModel 的默认实现是 Pacejka 简化式(魔术公式的一阶近似),够用,但别指望拟合真实轮胎数据——那是专业车辆仿真软件的领域。
传动:扭矩的分配路径
UVehicleEngine 不是渲染用的引擎,是扭矩源:Throttle 查扭矩曲线(Torque Curve asset)得当前 RPM 下的峰值扭矩,经变速箱(Forward Gears 表的齿比 + 最终传动比)放大,再按差速器配置(前驱/后驱/四驱的 Differential Type)分配到驱动轮。刹车同理, BrakeTorque 直接加在轮子上。
一个常见的错误认知:Max Torque 配很大而齿比很小,以为能加速快——其实轮端扭矩 = 扭矩 × 总齿比,而轮速 = 引擎转速 / 总齿比。齿比决定的是每个档位里引擎转速区间怎么映射到车速区间,加速感的来源是"当前车速下 RPM 是否在峰值扭矩区"。调加速先看齿比表,再看扭矩曲线。
联机载具:为什么手感最难保
载具状态(速度、轮速、悬挂压缩)每帧都在变,网络复制走的是和 CharacterMovement 不同的路:MovementComponent 复制FFixedVehiclesState 快照,客户端本地做简单预测、靠服务器校正回滚。问题在于载具对速度连续性的敏感度远高于角色:校正位移 10cm,角色玩家无感,载具玩家明显感到"拽了一下",因为悬挂力和轮胎力都是速度的函数,位移突变会连带把力算错一帧。
实践上的缓解手段:载具的 NetUpdateFrequency 给足(载具移动快,默认 30Hz 偏低);Replication 上把悬挂/轮子动画和物理状态解耦(轮子视觉转速本地插值,不强同步);对驾驶手感要求高的项目(竞速类),考虑客户端权威速度 + 服务器校验的反作弊折中,而不是默认的服务器权威。
源码入口
- 核心循环:
ChaosVehicles模块ChaosVehicleManager.cpp的FChaosVehicleManager::Tick,看轮子更新怎么挂进求解器回调; - 悬挂/轮胎:
FWheelInstance和FTireModel(ChaosVehicles/TireModels.h),射线悬挂力计算在UChaosVehicleMovementComponent::GetSuspensionForces附近; - 传动:
UVehicleEngine::FindPeakTorque一族,看扭矩曲线采样和 RPM 积分; - 联机状态:
ChaosVehicle模块的FFixedVehiclesState结构,复制路径在UChaosWheeledVehicleMovementComponent::GetReplicationSnapshots。
数据流示意: