Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

物理问题的故障排除

使用物理引擎时,你可能会遇到一些意想不到的问题。

虽然其中许多问题可以通过配置解决,但其中一些问题是引擎错误造成的。有关物理引擎相关的已知问题,请参阅 GitHub 上开放的物理相关问题。阅览已关闭的问题也可以帮助你解答与物理引擎行为相关的问题。

高速运动的对象会互相穿透

这种情况被称为穿透(tunneling)。在刚体(RigidBody)的属性中开启连续碰撞检测(Continuous CD)有时可以解决这个问题。如果这没什么用,你还可以尝试以下几种其他的解决方案:

  • 使你的静态碰撞形状更厚。例如,如果你有一个玩家不会以某种方式穿过去的薄地板,你可以使其碰撞体比视觉表现更厚。

  • 根据快速移动物体的运动速度调整其碰撞形状。物体移动得越快,碰撞形状应该向外扩展得越多,以确保它能够更可靠地与薄墙发生碰撞。

  • 在高级项目设置中增加每秒物理周期数。虽然这有其他好处(例如更稳定的模拟和减少输入延迟),但这会增加 CPU 使用率,可能不适用于移动/网页平台。对于大多数显示器来说,应该优先选择默认值 60 的倍数(如 120180240),以获得平滑的外观。

堆叠的对象不稳定且摇摆不定

尽管看起来像个简单问题,但在物理引擎中实现稳定的堆叠 RigidBody 的模拟却很困难。这是因为积分力的作用方向相互对立。堆叠的物体越多,相互之间的作用力就越强。这最终会导致模拟变得不稳定,使得物体无法在不移动的情况下相互堆叠在一起。

提高物理模拟速率有助于缓解这个问题。为此,可以在高级项目设置中增加每秒物理周期数。请注意,这会增加 CPU 使用率,可能不适用于移动/网页平台。对于大多数显示器来说,应该优先选择默认值 60 的倍数(如 120180240),以获得平滑的外观。

在 3D 中,将物理引擎从默认的 GodotPhysics 切换为 Jolt 也可以提高稳定性。更多信息请参阅使用 Jolt Physics

缩放后的物理体或碰撞形状无法正确碰撞

Godot 目前不支持缩放物理体或碰撞形状。作为替代方案,应更改碰撞形状的范围而不是其缩放比例。如果你想让视觉表现的尺寸也发生变化,可以分别更改底层视觉表现(Sprite2D、MeshInstance3D……)的缩放比例以及碰撞形状的范围。在这种情况下,请确保碰撞形状不是视觉表现节点的子节点。

由于资源默认是共享的,如果你不想让更改应用于场景中使用相同碰撞形状资源的所有节点,你需要让这个碰撞形状资源变得唯一。这可以通过以下两种方式实现:

  • 在编辑器中,点击检查器内 CollisionShape 资源下拉菜单中的 Make Unique,然后更改其大小。

  • 在脚本中,通过在修改其大小 之前,对碰撞形状资源调用 duplicate() 方法来实现。

薄物体放在地板上时会摇摆不定

这可能是由以下两个原因之一造成的:

  • 地板的碰撞形状太薄了。

  • RigidBody 的碰撞形状太薄了。

在第一种情况下,问题可以通过加厚地板的碰撞形状来缓解。例如,如果你有一个玩家不会以某种方式穿过去的薄地板,你可以使其碰撞体比视觉表现更厚。

在第二种情况下,问题通常只能通过提高物理模拟速率来解决(因为使形状更厚会导致 RigidBody 的视觉表现与其碰撞之间出现脱节)。

在两种情况下,提高物理模拟速率都有助于缓解这个问题。为此,可以在高级项目设置中增加每秒物理周期数。请注意,这会增加 CPU 使用率,可能不适用于移动/网页平台。对于大多数显示器来说,应该优先选择默认值 60 的倍数(如 120180240),以获得平滑的外观。

圆柱碰撞形状不稳定

将物理引擎从默认的 GodotPhysics 切换为 Jolt 可使圆柱碰撞形状更加可靠。更多信息请参阅使用 Jolt Physics

在 Godot 4 从 Bullet 过渡到 GodotPhysics 的期间,圆柱碰撞形状不得不从头开始重新实现。然而,圆柱碰撞形状是最难支持的形状之一,这也是为什么许多其他物理引擎完全不提供支持。目前已知圆柱碰撞形状存在一些问题。

如果你坚持使用 GodotPhysics,我们建议目前对角色使用盒形或胶囊形碰撞形状。盒形通常提供最佳的可靠性,但缺点是会让角色在对角线方向上占用更多空间。胶囊形碰撞形状没有这个缺点,但其形状可能会使精确的平台跳跃更加困难。

VehicleBody 模拟不稳定,尤其是在高速时

当物理体高速移动时,它在每个物理步长之间会移动很长的距离。例如,在 3D 中使用 1单位 = 1 米的惯例时,一辆以 360 km/h 速度移动的车辆每秒会移动 100 个单位。使用默认的 60 Hz 物理模拟速率时,车辆每个物理周期移动约 1.67 个单位。这意味着小物体可能被车辆完全忽略(由于隧道效应),同时也意味着在如此高的速度下,模拟通常只有很少的数据可供处理。

快速移动的车辆可以从提高物理模拟速率中获益良多。为此,可以在高级项目设置中增加每秒物理周期数。请注意,这会提高 CPU 使用率,可能不适用于移动/网页平台。对于大多数显示器来说,应该优先选择默认值 60 的倍数(如 120180240),以获得平滑的外观。

物体在图块间移动时,碰撞发生磕碰

这是物理引擎中的一个已知问题,由物体在形状边缘发生碰撞引起,即使该边缘被另一个形状覆盖。这在 2D 和 3D 中都可能发生。

解决此问题的最佳方法是创建一个“复合”碰撞体。也就是说,不为每个单独的图块设置碰撞,而是创建一个单独的碰撞形状,用于表示一组图块的碰撞。通常,你应该按照连通区域(即每一组相互接触的图块各自拥有一个碰撞体)来划分复合碰撞体。

使用复合碰撞体在某些情况下也可以提高物理模拟性能。然而,由于复合碰撞形状要复杂得多,这并非在所有情况下都能带来整体性能上的提升。

小技巧

在 Godot 4.5 及更高版本中,使用 TileMapLayer 节点时会自动创建复合碰撞体。可以通过 TileMapLayer 检查器中的 Physics Quadrant Size 属性设置区块尺寸(默认为每个轴 16 个图块)。较大的值可提供更可靠的碰撞效果,但会在修改 TileMap 时导致更新速度变慢。

物体接触另一个物体时帧率下降

这很可能是因为其中一个物体使用的碰撞形状过于复杂。出于性能原因,凸碰撞形状应尽可能使用最少数量的形状。当依赖 Godot 的自动生成时,你可能会为单个凸碰撞形状资源创建数十甚至数百个形状。

在某些情况下,用几个基本碰撞形状(盒形、球形或胶囊形)替换凸碰撞体可以带来更好的性能。

这个问题也可能发生在使用非常详细的三角网格(凹形)碰撞的 StaticBody 上。在这种情况下,应使用简化的关卡几何表示作为碰撞体。这不仅可以显著提高物理模拟性能,还可以提高稳定性,因为简化过程中可以去除小型固定物件、填补缝隙。

在 3D 中,将物理引擎从默认的 GodotPhysics 切换为 Jolt 也可以提高性能。更多信息请参阅使用 Jolt Physics

超过一定物理模拟周期后帧率突然降至非常低的值

发生这种情况是因为物理引擎无法跟上预期的模拟速率。在这种情况下,帧率会开始下降,但引擎每帧只允许模拟一定数量的物理步骤。这会像滚雪球一样导致帧率不断下降,直到达到非常低的帧率(通常为 1-2 FPS),这被称为物理死亡螺旋

为避免这种情况,你应该检查项目中可能导致同时发生过多物理模拟(或使用过于复杂的碰撞形状)的情况。如果这些情况无法避免,你可以增加每帧最大物理步数和/或降低每秒物理周期数项目设置来缓解这个问题。

远离世界原点时物理模拟不可靠

这是由浮点精度误差引起的,随着物理模拟发生的位置远离世界原点会变得愈发明显。这个问题也会影响渲染,导致远离世界原点时相机移动出现抖动。有关更多信息,请参阅大世界坐标