资讯详情

资讯详情

物理引擎动力学参数调试全攻略:从刚体、摩擦到阻尼迭代一次讲透

搞物理模拟最让人头疼的就是“动力学参数设置”这几个字。看起来只是填几个数字但稍有不对物体会像被风吹跑一样乱飘或者落地之后原地抖个不停严重的直接穿模穿到地心去。我在这个坑里反复摔了几年现在基本扫一眼现象就能猜到是哪个参数在捣乱。这篇文章就把我积累的经验整理出来按“底层逻辑—基础参数—接触参数—阻尼与求解—关节约束—实战排查”的顺序讲透对于调参总是调不明白或者刚接触物理引擎还不清楚各参数之间内在联系的开发者应该能省下大量瞎试的时间。1. 动力学参数设置的核心思路与底层逻辑很多新手拿到物理引擎的第一反应是质量给个 1摩擦给个 0.5弹性给个 0然后跑一下——结果发现跟想象完全不一样。其实这不是引擎的问题是我们没搞懂动力学参数到底是干什么用的。1.1 动力学参数到底解决什么问题先理解一个核心事实现代物理引擎在实时模拟时并不是真的在精确解物理方程而是在每个时间步里做一次“近似求解”。动力学参数本质上就是喂给这个求解器的边界条件。稳定性迭代不收敛、抖动、爆炸都和参数给得不合理有关。真实感参数决定了物体看起来“重不重”“滑不滑”“弹不弹”。性能某些参数比如迭代次数、接触块大小直接决定了物理计算的开销。拿一个掉在地上的球来说。如果质量特别大碰撞时的冲量就大约束求解器需要更多迭代才能稳住如果物体的恢复系数很高速度在碰撞后几乎不损失多次弹跳后依旧剩下不少动能看起来就很“假”。所以动力学参数不是在“设置物体的属性”而是在“告诉求解器该怎么处理物体之间的关系”。1.2 参数之间的耦合关系动力学参数最容易被忽视的是它们之间高度耦合。单独把某个参数调到“自认为合理”其他参数不配合最后结果依然崩。举个例子摩擦系数和恢复系数不是独立的。一个恢复系数为 0 的物体撞到地面法向速度变成 0这时摩擦才会显著起效。但如果你把恢复系数调到 0.8物体撞地后还会往上弹计算摩擦的时间变短实际滑动的距离反而变长了。阻尼也和重力加速度耦合。如果你的场景里重力加速度调的比默认值大线性阻尼不跟着提高物体会出现一种“又重又飘”的违和感——下落很快但速度一进来就被阻尼吃掉一大块停得突兀。所以真正靠谱的调参方法不是“哪个参数不对就调哪个”而是先搞清楚现象背后涉及哪几个参数再一起调。后面我会专门讲这套排查思路。2. 刚体基础参数质量、密度、质心与睡眠参数刚体参数是整个动力学的基石。很多看起来复杂的异常行为追到根上就是一个刚体参数设置错了。2.1 质量与密度优先用密度而不是直接给质量在大多数物理引擎里你可以直接指定质量也可以指定密度让引擎根据体积计算质量。我强烈建议用密度除非有特殊需求。为什么因为质量是一个“标量”它不携带形状信息。同一个质量分布在一个大木箱上和分布在一个小铁球上物理行为完全不同。用密度的话引擎会根据碰撞体的体积自动计算质量这不仅更真实也能避免你手工为每个物体填质量时遗漏或填错。举个例子一个半径 1 米、密度为 1 的球体体积大约是 4.19 立方米质量就是 4.19。同样一个球密度调到 7.8质量就是 32.6 左右——大约 7.8 倍。这个差距直接决定它撞到别人时谁被推得更远。所以在做一辆车、一个角色、一堆杂物的时候先想想它们的真实材质密度大概是多少再设置参数。直接给质量的场景也有但在用的时候要额外小心因为引擎求解约束时依赖质量比来计算冲量分配如果你把两三个物体的质量都设成 1比例完全一样就会出现“大箱子推不动小石头”的搞笑物理效果。2.2 质心偏移不能忽略比质量更容易被忽略的是质心位置。很多引擎允许你手动设置质心的局部坐标默认情况下它会取碰撞体的几何中心。但这只在物体密度均匀时才成立。实际项目中我见过一个“翻车幽灵”案例一辆小车车身模型没问题但碰撞体是把几个长方体简单拼出来的质心被默认算在了整个组合体的中心而实际电池、引擎、乘客的重量都在偏后偏下的位置。结果车在刹车时后轴总是抬起来转弯时侧翻概率大增。这不是物理引擎的问题是质心没调对。排查方法也很直接给物体一个初始角速度看它是否绕着你期望的轴稳定旋转。如果旋转轴在漂移或者静止时物体明显倾斜十有八九就是质心位置不合理。2.3 睡眠参数性能与稳定的隐形开关刚体的睡眠参数sleep threshold平时很少人关注但它直接影响性能和稳定性。所谓睡眠就是物体速度和角速度低于某个阈值持续一段时间后引擎判定它“睡着了”不再参与物理求解。这个机制非常有用。一个场景里堆了几百个箱子如果它们永远处于激活状态每个时间步都要做接触求解性能直接崩掉。睡眠就是让静止物体“退休”大幅减少计算量。参数设置经验是这样的阈值设得太大物体稍微碰一下就“睡死”了玩家踢一脚没反应体验很差。阈值设得太小物体永远不睡觉性能白损耗而且微小的数值抖动会被不断放大表现为物体缓慢漂移。我一般把睡眠阈值设为默认值的一半左右然后单独检查“长时间静止后是否还会自移动”。如果自移动就适当提高阈值而不是去调求解器。3. 接触与材质参数摩擦、恢复系数与碰撞行为刚体的稳定性调好之后物体之间怎么交互就归接触参数管了。摩擦和恢复系数是这里的两大主角。3.1 静摩擦与动摩擦为什么物体会打滑摩擦参数在大多数引擎里分成静摩擦和动摩擦。静摩擦是物体从静止到开始滑动需要克服的力动摩擦是匀速滑动时受到的阻力。如果一个物体放在斜面上慢慢往下滑而不是静止不动往往就是静摩擦不够。我的经验是一个大致参考地面和木箱静摩擦 0.7~0.8动摩擦 0.5~0.6。光滑冰面静摩擦 0.05动摩擦 0.03。金属之间的接触静摩擦 0.3 左右动摩擦 0.2 左右。注意动摩擦最好不要设为 0否则物体会在碰撞后表现出“永远滑下去”的诡异状态。除非你刻意做冰面关卡否则纯 0 摩擦会让玩家以为地面装了传送带。还有一个调参细节摩擦力的作用点在接触面中心如果你把两个物体的接触面做得很小比如用一堆细杆模拟一个平台摩擦力的表现会非常不稳定。这种情况下优先改碰撞体形状而不是死磕摩擦系数。3.2 恢复系数不是“弹性”是对冲量损失的模拟恢复系数这个概念我见过很多误解。它不是“弹性程度”而是碰撞后法向速度与碰撞前法向速度的比值。取值 0 代表完全非弹性碰撞碰撞后法向速度归零取值 1 代表完全弹性碰撞法向速度不损失。所以如果你想要“球落在地上弹几下然后停住”恢复系数取 0.5~0.6 就够了而不是 1.0。真正取 1.0 的后果是球永远不会停每次弹跳高度都一样看起来像反重力特效。另外不同物体碰撞时引擎默认会做组合计算。比如两个物体的恢复系数分别是 0 和 1按乘法组合就是 0按平均值组合就是 0.5。结果完全不同。调参之前先确认你用的组合模式是什么。3.3 摩擦组合模式怎么选主流物理引擎一般提供四类组合模式有必要把它们记住组合模式计算方式适用场景Average取平均值默认且通用不同材质混合时表现均衡Min取较小值模拟“光滑面优先”比如冰块合路面Multiply取乘积需要强烈反差时混合结果更极端Max取较大值模拟“粗糙面优先”比如粗糙水泥地我在项目里最常用的组合是 Average因为它的可预测性最好。如果你遇到“明明把摩擦设定的很高但物体还是滑”的情况优先检查组合模式大概率是被 Min 或 Multiply 把数值拉低了。3.4 接触法线与边缘摩擦的实际影响很多人调的摩擦在理论计算里没问题但一跑起来就废原因在于接触几何有问题。最常见的是用非常薄的盒子做地板碰撞体只有一条边缘接触到球体接触面小摩擦表现极不稳定。这种问题从参数上基本调不出来唯一办法是给碰撞体加厚度或者换成凸包碰撞体。经验值任何作为“地面”的碰撞体厚度至少要在 0.1 以上否则高速度物体冲过来时引擎很容易把接触点算在边缘尖角上产生奇怪的弹射。4. 阻尼与运动学限制参数手感调优的关键旋钮阻尼是“手感”的灵魂。质量和摩擦决定物体在静态接触下的表现阻尼则决定物体在空中和运动中的体感。4.1 线性阻尼与角阻尼的适用场景线性阻尼模拟的是空气阻力它会让速度随时间指数衰减。角阻尼则让物体旋转变慢。默认值通常接近 0表现是物体失去推力后会滑行很远、转个不停——这在物理上没错但在游戏手感里往往是灾难。我的调参心得做“沉重感”的角色或载具时线性阻尼调到 0.5~1.0角阻尼调到 0.5~1.0。做飘浮、太空场景时两个阻尼都调 0营造无阻力的感觉。做爆炸冲击效果时临时调低阻尼让碎片飞得更远等特效结束后再调回正常值。需要注意的是阻尼不是越高越好。线性阻尼过高会让物体运动显得“胶水一样黏”下落过程中突然减速非常不自然。角阻尼过高则会导致旋转物体在碰撞时没有足够的转动反馈看起来像被定住一样。4.2 最大速度与最大角速度限制引擎为了防止数值失控会给物体设置最大速度限制。这项参数平时不用动但做高速运动物体比如子弹、赛车时一定要检查。如果你把一枚子弹的速度设成 500 米/秒而默认最大速度只有 100引擎会直接截断速度导致子弹飞得比预期慢高空抛物时还会出现轻飘飘的感觉。更大问题是“隧穿”——物体速度快到在一个物理时间步内穿越了整个碰撞体引擎完全检测不到碰撞。处理方式有两个方向提高最大速度限制同时调高物理子步数比如一帧做 4 次子步保证高速物体不会穿模。对于子弹这类高速小物体不依赖物理碰撞改用射线检测raycast配合物理参数做简化模拟。4.3 速度迭代与位置迭代次数的平衡迭代次数是物理引擎里最难直观理解、也最能决定稳定性的参数。它决定求解器每帧用多少轮迭代来修正速度误差和位置误差。直觉上迭代次数越多越稳定但实际表现是速度迭代多了堆叠物体不容易滑动位置迭代多了穿透纠正更快。问题在于迭代是要花时间的翻倍可能让物理性能直接打五折。经验参考值默认速度为 8、位置为 4 左右适合大多数场景。堆叠物体比如积木塔出现抖动时把速度迭代调到 12~16先把速度误差压住。物体穿透频繁时把位置迭代调到 6~8并同时确认最大速度不过高。调迭代次数前先确认时间步长是干净的。如果你在渲染帧率不稳定时直接把固定时间步长拉大再调迭代次数也救不回来。5. 关节与约束参数调试让连接件不抖不飘关节joint是动力学里最容易让人血压飙升的部分。无论是门铰链、机械臂、汽车悬挂还是布娃娃调不好的表现基本都是两种抖动或者漂移。5.1 约束漂移的本质关节的本质是一个约束方程它规定两个刚体之间的相对位置和角度差必须保持某个值。但物理引擎是分步求解的每帧只能修正一部分误差所以实际结果总是会有积累误差。约束漂移就是这个误差的宏观体现。最常见的表现形式一个用铰链连接的门开着开着角度慢慢变大或者关门时回弹一下。原因通常是位置迭代次数不够导致每次修正都不彻底误差一点点累积。我常用的一种排查方法把时间步长缩小一半看漂移是否明显减少。如果减少说明是求解精度不够优先调迭代次数如果毫无变化说明约束本身设置有毛病比如锚点位置错了。5.2 弹簧与马达参数的经验调法很多关节都支持驱动器比如弹簧、马达。这个驱动器的参数有三个核心量刚度、阻尼、最大输出力。刚度过大约束会被“拽”得很紧但只要一超限就容易抖动类似吉他弦拨动后的高频振动。刚度过小物体会像果冻一样软绵绵。阻尼的作用是抑制振动阻尼越大反馈越迟钝但越不容易抖阻尼越小反馈越灵敏但更容易产生振荡。调参数我的习惯是先定刚度再调阻尼最后限制最大力刚度从 0 开始慢慢加直到物体回到目标位置的速度“快但无感”。阻尼调到刚度的 0.2~0.3 倍左右作为初始值再根据抖不抖微调。最大输出力设为目标工况下所需推力的 1.2~1.5 倍留出余量又不至于过冲。举个实际例子我做机械臂的关节电机目标是把一段 2 米长的臂在 1 秒内抬到指定角度。先粗调刚度到能快速响应发现末端有点抖于是把阻尼往上加抖动消失后再把最大力限制在电机标称扭矩附近防止它把整辆小车掀翻。6. 实战调优方法从现象反推参数问题前面讲的都是单个参数到了真实环境里问题很少是单一参数引起的。更重要的是学会“看现象定位参数”。6.1 常见异常现象与参数排查对照表这张表是我每次调试都会对照的速查表建议按这个顺序走先看稳定性再看手感最后看性能。异常现象可能原因优先检查项物体落地后持续抖动迭代次数不足 / 恢复系数过高速度迭代提到 12恢复系数降到 0.2堆积物体缓慢滑动摩擦组合被拉低 / 静摩擦太低检查组合模式静摩擦调到 0.6 以上高速子弹穿过墙壁最大速度过大 / 子步数不足调大子步数或改用射线检测物体静止后缓慢漂移睡眠阈值太小 / 阻尼太低提高睡眠阈值或把阻尼加到 0.8关节回弹且晃个不停驱动器刚度过大 / 阻尼不足降低刚度增加阻尼车转弯就翻质心偏高 / 悬架刚度不够下移质心增加悬架刚度物体被推一下飞得离谱恢复系数被组合成 1 / 阻尼为 0恢复系数降到 0.1阻尼加 0.5先看表格里和自己现象最像的一行把优先检查项调到位90% 的诡异行为都能解决。6.2 参数梯度测试法遇到多个参数同时可疑的时候不要直接“凭感觉一起改”——一次只改一个参数改完跑一遍记录结果再改下一个。这是我从工程调试里学到最实用的方法论。具体做法是把当前参数组合存成一份基线配置。选一个可疑参数从基线值往上调 50%跑一遍记录是否变好。再往下调 50%跑一遍记录是否更差。如果两个方向都变差说明基线值就是局部最优如果一个方向变好就顺着那个方向继续二分步进。确定这个参数后再选下一个参数重复。这套方法看着蠢但比“连改五个参数后不知道是哪一步救了回来”要高效得多。每一次都留下记录下次遇到类似现象直接翻记录省下的时间远超调参本身。还有一个独门技巧很多物理引擎支持在运行时动态修改参数。调试不要停下来改代码再重新跑应该把参数暴露到控制台或者调试面板上用滑条实时调整。这样你几乎马上就能感受到参数对物理行为的影响比改一次跑一次快十倍以上。7. 写在最后的实战体会动力学参数设置没有一劳永逸的“标准答案”但有几个原则基本上每次都适用优先用密度代替直接质量、每次只改一个参数并做记录、稳定输出优先于物理正确性、以及永远先检查碰撞体几何是否正确再调参数。我见过太多人花几个小时去调摩擦最后发现是碰撞体太薄导致的接触点异常。搞物理模拟的第一课不是学公式而是学会怀疑自己的每个假设。这是我的经验也是新手最容易忽视却收获最大的一步。调参这东西急不来但只要思路对了参数是会开口说话的。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →