4、材质与摩擦:物理材质的定义,摩擦系数与恢复系数(弹性)的实际调参经验

好,咱们今天聊点实在的。物理材质这个东西,说白了就是告诉物理引擎:「这个物体摸起来像什么?」是像冰面一样滑,还是像橡胶一样弹?

我刚开始做物理集成的时候,以为只要把刚体加上重力就完事了。结果呢?物体掉地上直接弹飞了,或者两个箱子叠在一起像抹了油一样滑开。嗯,这就是没调好材质参数。

4.1 物理材质的核心属性

在Three.js里集成物理引擎(比如Cannon-es或Ammo.js),每个刚体都需要绑定一个材质。这个材质主要管两件事:

  • 摩擦系数(Friction):物体表面有多「涩」
  • 恢复系数(Restitution):物体有多「弹」

我个人习惯把这两个参数看作一对「冤家」。摩擦大了就不容易滑,恢复大了就容易弹。但两者之间其实没有直接数学关系,你得分别调。

4.2 摩擦系数的调参经验

摩擦系数一般取值在0到1之间。0代表完全光滑,1代表非常粗糙。但实际项目中,我很少用极端值。

材质类型 摩擦系数 典型场景
冰面 0.01 - 0.05 滑冰、推箱子
金属 0.3 - 0.5 机械零件、工具
橡胶 0.7 - 0.9 轮胎、鞋底
砂纸 0.9 - 1.0 打磨、防滑表面

我在项目中遇到过一个问题:一个木箱放在木地板上,按理说应该能稳稳停住。但实际跑起来,箱子轻轻一推就滑出去老远。后来发现是摩擦系数设成了0.2,改成0.5就正常了。你想想看,木头之间的摩擦其实不小,0.2太低了。

调参小技巧: 如果你不确定摩擦系数该设多少,先从0.5开始试。然后观察物体滑动的情况,再微调。每次调0.05的步长,别一次跳太大。

4.3 恢复系数(弹性)的调参经验

恢复系数决定了物体碰撞后能「弹」回多少能量。1代表完全弹性(像超级球),0代表完全非弹性(像一袋面粉)。

材质类型 恢复系数 典型场景
超级球 0.9 - 1.0 弹跳球、蹦床
篮球 0.7 - 0.8 运动模拟
木头 0.2 - 0.4 家具、地板
沙袋 0.0 - 0.1 软体、缓冲

为什么会这样?因为现实世界中没有完全弹性的物体。就算是一个钢球掉在钢板上,也会损失一部分能量(变成声音和热量)。所以恢复系数永远小于1。

我曾经犯过一个错误:把恢复系数设成1.0,结果一个球掉地上后越弹越高,最后直接飞出场景了。嗯,物理引擎可不会跟你讲客气,参数设得离谱,行为就离谱。

避坑指南: 恢复系数不要超过1.0!我曾经手滑设成了1.2,结果物体碰撞后速度反而增加了,整个物理模拟直接炸掉。物理引擎不是游戏,它不会帮你做能量守恒的校验。

4.4 代码示例:在Cannon-es中定义物理材质

下面是一个实际的代码片段,展示了如何在Cannon-es中创建材质并应用到刚体上:

// 创建物理材质
const groundMaterial = new CANNON.Material('ground');
const boxMaterial = new CANNON.Material('box');

// 定义接触材质对
const contactMaterial = new CANNON.ContactMaterial(
  groundMaterial,
  boxMaterial,
  {
    friction: 0.5,      // 摩擦系数
    restitution: 0.3    // 恢复系数
  }
);

// 添加到物理世界
world.addContactMaterial(contactMaterial);

// 应用到刚体
const groundBody = new CANNON.Body({ mass: 0, material: groundMaterial });
const boxBody = new CANNON.Body({ mass: 1, material: boxMaterial });

注意看,这里我用了ContactMaterial来定义两种材质之间的交互参数。为什么不是直接在材质上定义?因为摩擦和恢复其实是「两个物体之间」的属性,不是单个物体的属性。一个橡胶球在冰面上和在砂纸上的表现完全不同,对吧?

4.5 实际调参经验总结

做了几个项目后,我总结了一套自己的调参流程:

  1. 先调恢复系数:让物体掉地上,观察弹跳高度。如果弹得太高就降低,如果完全不弹就提高。
  2. 再调摩擦系数:推一下物体,看它滑多远。滑得太远就提高摩擦,停得太快就降低。
  3. 最后微调:两个参数一起调,因为有时候摩擦和恢复会互相影响。比如恢复系数高了,物体弹跳时接触时间短,摩擦效果就不明显。
核心经验: 物理材质的调参没有「标准答案」。同一个物体在不同场景下需要的参数完全不同。我的建议是:先做出一个「看起来合理」的效果,然后让测试人员玩一玩,根据反馈再调。别想着一次调到位,物理模拟这东西,永远有优化空间。

好了,这一章就到这里。下一章我们会聊碰撞检测的优化,到时候我会分享一些让物理模拟跑得更流畅的实战技巧。记得动手试试上面的代码,亲手调一调参数,比看十遍文章都管用。