60.碰撞体的缩放位置质量

60.性能优化-CPU-物理-碰撞体缩放位置质量


60.1 知识点

尽量保证物理对象的缩放大小

建议尽量保持物理对象的缩放为 (1,1,1)

原因:

  1. PhysX 的很多容差(接触偏移、皮肤宽度、求解步长等)是按 1 unit = 1 m 的数量级调参的
  2. 物体过小(小于约 0.1m)或过大(大于约 10–50m),更容易出现穿透、抖动、关节数值不稳等问题
  3. 非均匀缩放还会让碰撞几何与惯性张量的计算更复杂,稳定性更差

因此,为避免增加物理计算压力和稳定性问题,建议尽量保持物理对象的缩放为 (1,1,1)

示例:检查碰撞体缩放

// 在编辑器中检查物理对象缩放是否合理
if (transform.localScale != Vector3.one)
{
    Debug.LogWarning($"物体 {gameObject.name} 缩放非 (1,1,1),可能影响物理稳定性");
}

尽量保持对象在世界空间原点位置

建议保持对象在世界空间的位置尽量接近世界空间原点 (0,0,0)

原理:32 位 float 的精度是“相对”的

Unity 的 Vector3 每个分量都是 32 位 float。问题在于:float 在数轴上的精度不是均匀的。离 0 越远,能表示的数字越稀疏,精度越差。

打个比方:像一把尺子,刻度在 0 附近很密(1mm 一个刻度),在 1000m 处就变得很稀疏(可能 1m 才一个刻度)。所以 1.001 和 1.002 能区分,但 1000.001 和 1000.002 在这把尺子上可能都落在同一个刻度上。

技术原因:IEEE 754 浮点数结构

32 位 float 分三部分:1 位符号、8 位指数、23 位尾数。尾数位决定“有效数字位数”,指数决定“数量级”。
23 位尾数一共能表示约 800 万个不同的数值,但这 800 万个值分布在哪个区间,由指数决定。

  • 指数小(如 1.0 附近):这 800 万个值分布在 1.0~2.0 之间,相邻两个可表示数的差约 1.2e-7,能区分 1.0000001 和 1.0000002。
  • 指数大(如 100 万附近):同样 800 万个值分布在 1e6~2e6 之间,相邻差约 0.12,1,000,000.1 会被舍入到 1,000,000.0,无法精确表示。

结论:尾数位数固定,但指数越大,每个“刻度”代表的实际距离越大,绝对精度就越差。

在 Unity 里的表现

  1. 渲染抖动
    物体在 (10000, 0, 0) 附近时,顶点坐标 10000.001 和 10000.002 可能被舍入到同一个 float。摄像机移动或物体旋转时,不同帧会舍入到不同刻度,导致顶点在屏幕上“跳”,看起来就是抖动。
  2. 物理抖动
    物理引擎需要算位移、速度、碰撞距离。坐标大时,这些微小的量会被舍入掉,产生错误。表现为:刚体静止时微颤、关节拉扯、穿模、弹飞、轨迹计算异常。
  3. 其他系统
    动画骨骼、粒子、3D 音频等,只要涉及世界坐标计算,都会受影响。

实践建议:浮动原点

把玩家“秘密”传送回原点附近,让场景跟着平移。例如玩家进洞穴再出来时,把场景内所有对象(地形、静态物、刚体、粒子、导航、音源等)整体平移一个偏移量,使玩家回到 (0,0,0) 附近。玩家视觉上没感知,但物理坐标已回到精度高的区间。这种做法在开放世界、大场景项目中很常见。

尽量保证合理的质量关系

PhysX 默认把 Unity 中的质量当千克(kg)。
推荐使用真实数量级(人 70–90kg,车 1200–2000kg),或在全局统一按常数缩放(例如全部质量 ÷ 80),但需保证所有相关力、阻尼、弹簧参数也随之成比例调整,避免相对量级被破坏。

避免极端质量:

  1. 极小的质量(小于 0.01kg)
  2. 极大的质量(大于 10000kg)

这样容易产生数值问题。
若表现“大质量不能被推动”的物体,应使用静态碰撞器或运动学刚体,而不是给超大质量。

质量比建议:
常见交互体的质量比应尽量小,最好控制在 20:1 以下。
过大比值会导致冲量极端、速度骤变、解算不稳定等问题。
例如:人 80kg,与其碰撞的对象质量最好不超过 1600kg。
若存在显著质量差异的对象,应尽可能通过碰撞层矩阵配置剔除,避免出现问题。


60.2 知识点代码

Lesson60_性能优化_CPU_物理_碰撞体缩放位置旋转.cs

public class Lesson60_性能优化_CPU_物理_碰撞体缩放位置旋转
{
    #region 知识点一 尽量保证物理对象的缩放大小

    //尽量保证物理对象的缩放为(1,1,1)
    //原因:
    //PhysX的很多容差(接触偏移、皮肤宽度、求解步长等)
    //是以 1unit=1m 的数量级进行默认调参的
    //把物体做得过小(<~0.1m)或过大(>~10–50m),更容易出现穿透、抖动、关节数值不稳等问题
    //非均匀缩放还会让碰撞几何与惯性张量的计算更复杂,稳定性更差
    //因此为了避免增加物理计算压力和稳定,建议保证物理对象的缩放不变

    #endregion

    #region 知识点二 尽量保持对象在世界空间原点位置

    //建议保持对象在世界空间的位置尽量接近世界空间原点(0,0,0)
    //因为距离(0,0,0)越远,32位浮点的小数精度越差
    //表现为渲染抖动、碰撞抖动、关节发疯等等
    //比如:
    //如果是超大场景的游戏,玩家可能走数万米,那么有可能在远处时产生奇怪的物理表现
    //建议:
    //我们可以秘密地将玩家传送到世界空间的原点(0,0,0)
    //可以在玩家 进入一个洞穴后出来时
    //把场景内所有对象(含地形、静态物、刚体、粒子、导航、音源等)整体平移一个偏移量
    //让玩家还是感受在原来的位置
    //但实际上,坐标已经回到原点附近

    #endregion

    #region 知识点三 尽量保证合理的质量关系

    //PhysX 默认把Unity中质量当千克(kg)
    //推荐直接使用真实数量级(人 70–90kg,车 1200–2000kg)
    //或者
    //在全局统一按常数缩放(例如全部质量÷80)
    //但要保证所有相关力、阻尼、弹簧参数也随之成比例调整,避免相对量级被破坏

    //我们应该尽量避免极端质量情况
    //比如
    //极小的质量(小于0.01kg)
    //极大的质量(大于10000kg)
    //这样会容易产生数值问题
    //如果想表现那种大质量不能被推动的物体,可以使用静态碰撞器或者运动学刚体实现
    //而不是给一个超大质量

    //常见交互体的 质量比 应尽量小一些,最好控制在20:1以下
    //因为过大的比值会导致冲量极端、速度骤变、解算不稳定等问题
    //比如
    //一个人80kg,最好和自己产生碰撞对象的质量不要超过1600kg
    //如果存在显著质量差异的对象应尽可能使用碰撞层矩阵配置对他们进行剔除,避免出现问题

    #endregion
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏