U1L13-1——物理系统之刚体

刚体 ** (Rigidbody)**

刚体 (Rigidbody) 是实现游戏对象的物理行为的主要组件。连接刚体后,对象将立即响应重力。
如果还添加了一个或多个__碰撞体__组件,则游戏对象会因发生碰撞而移动。
由于刚体组件会接管附加到的游戏对象的运动,因此不应试图借助脚本通过更改变换属性(如位置和旋转)来移动游戏对象。
相反,应该施加来推动游戏对象并让物理引擎计算结果。
在某些情况下,可能希望游戏对象具有刚体,并让刚体的运动摆脱物理引擎的控制。
例如,可能希望直接从脚本代码控制角色,但仍允许触发器检测角色(请参阅碰撞体主题下的_触发器_)。
脚本产生的这种非物理运动称为_运动学_运动。刚体组件有一个名为 Is Kinematic 的属性,
该属性可以让刚体摆脱物理引擎的控制,并允许通过脚本以运动学方式来移动刚体。
可以通过脚本来更改 Is Kinematic 的值,从而为某个对象开启和关闭物理引擎,但这会产生性能开销,应谨慎使用。
有关这些组件的设置和脚本选项的更多详细信息,请参阅刚体2D 刚体参考页面。

刚体概述 - Unity 手册

刚体参数

碰撞产生的必要条件:两个物体都有碰撞器、至少一个物体有刚体

image

  • Mass - 质量(默认为千克)

    质量越大惯性越大

  • Drag - 空气阻力

    根据力移动对象时影响对象的空气阻力大小,0 表示没有空气阻力

  • Angular Drag - 根据扭矩旋转对象时影响对象的空气阻力大小

    0 表示没有空气阻力。

  • Use Gravity - 是否受重力影响

  • Is Kinematic - 是否是运动学物体

    如果启用此选项,则对象将不会被物理引擎驱动,只能通过 (Transform) 对其进行操作。对于移动平台,或者如果要动画化附加了 HingeJoint 的刚体,此属性将非常有用。

  • Interpolate - 插值运算,让刚体物体移动更平滑

    • None:不应用插值运算
    • Interpolate:根据前一帧的变换来平滑变换。
    • Extrapolate:差值运算,根据下一帧的估计变换来平滑变换。
  • Constraints - 约束 - 对刚体运动的限制

    • Freeze Position - 有选择地停止刚体沿世界 X、Y 和 Z 轴的移动。
    • Freeze Rotation - 有选择地停止刚体围绕局部 X、Y 和 Z 轴旋转。
  • Collision Detection - 碰撞检测模式

    不同原理碰撞检测各有优劣,详见下方:物理碰撞检测类型

    image

    • Discrete(离散检测)
    • Continuous(连续检测)
    • Continuous Dynamic(连续动态检测)
    • Continuous Speculative(连续推测式检测)

物理碰撞检测类型

  • Discrete(离散检测)

    对场景中的所有其他碰撞体使用离散碰撞检测。其他碰撞体在测试碰撞时会使用离散碰撞检测。用于正常碰撞(这是默认值)

    原理:每个物体只在 固定物理步长的采样点 检查是否与其他碰撞体重叠

    • 优点:性能最好,开销最小
    • 缺点:高速小物体可能在两帧之间跳过另一个碰撞体,出现穿透现象
    • 适用场景:绝大多数常速移动的物体(角色、箱子、环境物件)
  • Continuous(连续检测)

    对动态碰撞体(具有刚体)使用离散碰撞检测,并对静态碰撞体(没有刚体)使用连续碰撞检测。
    设置为连续动态 (Continuous Dynamic) 的刚体将在测试与该刚体的碰撞时使用连续碰撞检测,其他刚体将使用离散碰撞检测。
    (此属性对物理性能有很大影响,如果没有快速对象的碰撞问题,请将其保留为 Discrete 设置)

    原理:在两帧之间会额外做 运动轨迹的扫掠检测(sweep test),以减少穿透

    • 优点:大幅降低高速物体穿透的概率
    • 缺点:CPU 开销比 Discrete 高
    • 适用场景:非主角的小型高速物体(例如子弹、飞镖、投射物)
  • Continuous Dynamic(连续动态检测)

    性能消耗最高
    对设置为连续 (Continuous) 和连续动态 (Continuous Dynamic) 碰撞的游戏对象使用连续碰撞检测。
    还将对静态碰撞体(没有刚体)使用连续碰撞检测。对于所有其他碰撞体,使用离散碰撞检测。
    用于快速移动的对象。

    原理:比 Continuous(连续检测) 更严格,专门用于高速移动的刚体,它会检测所有 Continuous (连续检测)、Continuous Dynamic (连续动态检测)的物体

    • 优点:最稳妥地避免穿透
    • 缺点:开销最高,不适合大规模使用
    • 适用场景:关键的高速动态物体(例如主角手里的高速挥舞武器、主角发射的重要投射物)
  • Continuous Speculative(连续推测检测)

    对刚体和碰撞体使用推测性连续碰撞检测。该方法通常比连续碰撞检测的成本更低。

    原理:一种相对新的模式(比 Continuous(连续检测) 更轻量),会在下一帧前预测可能的碰撞,即使物体很小很快,也能避免大多数穿透

    • 优点:比 Continuous Dynamic(连续动态检测) 更省性能;避免了很多小物体穿透
    • 缺点:推测结果可能带来误判(没撞上也认为撞上了),偶尔出现虚假碰撞
    • 适用场景:中高速物体,既需要避免穿透,又不想消耗太多性能的情况

不同碰撞检测类型碰撞体相互使用的碰撞检测类型如下

无刚体碰撞盒 Discrete
(离散检测)
Continuous
(连续检测)
Continuous Dynamic
(连续动态检测)
Continuous Speculative
(连续推测检测)
无刚体碰撞盒 不检测碰撞 Discrete Continuous Continuous Continuous Speculative
Discrete
(离散检测)
Discrete Discrete Discrete Discrete Continuous Speculative
Continuous
(连续检测)
Continuous Discrete Discrete Continuous Continuous Speculative
Continuous Dynamic
(连续动态检测)
Continuous Discrete Continuous Continuous Continuous Speculative
Continuous Speculative
(连续推测检测)
Continuous Speculative Continuous Speculative Continuous Speculative Continuous Speculative Continuous Speculative

性能消耗关系:Continuous Dynamic > Continuous Speculative > Continuous > Discrete

刚体睡眠

当刚体移动速度低于规定的最小线性速度或转速时,物理引擎会认为刚体已经停止。
发生这种情况时,游戏对象在受到碰撞或力之前不会再次移动,因此将其设置为“睡眠”模式。
这种优化意味着,在刚体下一次被“唤醒”(即再次进入运动状态)之前,不会花费处理器时间来更新刚体。

在大多数情况下,刚体组件的睡眠和唤醒是透明发生的。
但是,如果通过修改__变换__位置将静态碰撞体(即,没有刚体的碰撞体)移入游戏对象或远离游戏对象,则可能无法唤醒游戏对象。
这种情况下可能会导致问题,例如,已经从刚体游戏对象下面移走地板时,刚体游戏对象会悬在空中。
在这种情况下,可以使用 WakeUp​ 函数显式唤醒游戏对象。有关睡眠的更多信息,请参阅刚体2D 刚体组件页面。

解决方法:rigidBody.WakeUp()