3D粒子碰撞

粒子碰撞

由于 GPU 粒子完全在 GPU 中处理,所以它们无法访问游戏中的物理世界。如果你需要粒子与环境碰撞,你必须设置粒子碰撞节点。共有四种:GPUParticlesCollisionBox3DGPUParticlesCollisionSphere3DGPUParticlesCollisionSDF3DGPUParticlesCollisionHeightField3D

通用属性

常用粒子碰撞属性

常用碰撞属性

有一些属性你可以在所有碰撞节点中找到。它们位于检查器的 GPUParticlesCollision3D 区域中。

Cull Mask 属性根据每个系统的 visibility layers 控制哪些粒子系统会受到碰撞节点的影响。仅当碰撞器的剔除遮罩中至少启用了一个系统的可见性层时,粒子系统才会与碰撞节点发生碰撞。

警告

Godot 4.0 中有一个与 GPU 粒子碰撞有关的`已知问题<https://github.com/godotengine/godot/issues/61014>`_ 这将阻止剔除遮罩正常工作。我们将在该问题被修复时更新文档。

盒型碰撞

粒子碰撞盒

节点列表中的盒型碰撞

盒子碰撞节点的形状像一个实心的矩形盒子。你可以使用 Extents 属性控制它们的大小。盒子范围始终测量其边界边的一半,因此值 (X=1.0,Y=1.0,Z=1.0) 将创建一个每边宽 2 米的盒子。箱体碰撞节点可用于模拟粒子应碰撞的地板和墙壁几何形状。

要创建盒型碰撞节点,请在场景中添加一个新的子节点,并在可选节点列表中选择 GPUParticlesCollisionBox3D。如果想要更多动态效果,你可以将节点位置动画化,或将它附加到其他移动节点上。

粒子系统的盒型碰撞

两个粒子系统与盒型碰撞节点碰撞

球形碰撞

粒子碰撞球

节点列表中的球面碰撞

球形碰撞节点的形状类似于一个实心球体。半径 Radius``属性控制球体的大小。盒型碰撞节点不一定是完美的立方体,但是球形碰撞节点始终是球体。如果要独立于高度设置宽度,则必须更改 3D节点``Node3D``部件中的缩放``Scale 属性。

要创建球体碰撞节点,添加一个新的子节点到你的场景,并从可用节点列表中选择 GPUParticlesCollisionSphere3D。可以动画化球体的位置或将其附加到一个移动的节点,以获得更加动态的效果。

粒子系统中的球面碰撞

两个粒子系统与球型碰撞节点碰撞

高度场碰撞

粒子碰撞高度场

节点列表中的高度场碰撞

高度场粒子碰撞对于参与粒子碰撞的大型室外区域非常有用。在运行时,节点会根据范围内的所有不被遮罩剔除的网格,创建一个高度场。粒子会与该高度场所代表的网格发生碰撞。由于高度场是动态生成的,因此它可以跟随玩家的摄像机移动,并对关卡中的变化做出反应。如果改变高度场的密度参数,性能也会有很大的调整。

要创建高度场碰撞节点,添加一个新的子节点到你的场景,并从可用节点列表中选择 GPUParticlesCollisionHeightField3D

高度场碰撞节点的形状像一个盒子。外延``Extents``属性控制其大小。外延属性总是测量其边界边长的一半,因此``(X=1.0,Y=1.0,Z=1.0)``的值会创建一个边长 2 米的盒子。在创建高度场时,会忽略外延以外的任何内容。

Resolution 属性控制高度场的详细程度。较低的分辨率会以牺牲准确性为代价提高执行速度。如果高度场分辨率太低,则可能看起来像粒子穿透关卡几何体或在碰撞事件期间卡在空中。它们还可能完全忽略一些较小的网格。

高度场分辨率

在低分辨率下,高度场碰撞会错过一些更精细的细节(左图)

更新模式``Update Mode``属性可以控制何时根据其范围内的网格重新创建高度场。将其设置为移动时``When Moved`` 可使其仅在移动时刷新。这种模式性能良好,适合不经常变化的静态场景。如果需要粒子与位置经常变化的动态物体碰撞,可以选择 "Always"(始终),使其每帧都刷新。这样做会影响性能,建议只在必要时使用。

备注

重要的是要记住,当更新模式``Update Mode`` 设置为 移动时``When Moved`` 时,是*高度场节点*的移动触发了更新。当场内的某个网格移动时,高度场不会更新。

启用跟随摄像机``Follow Camera Enabled``属性后,高度场将跟随当前摄像机。只要摄像机移动,它就会更新。该属性可用于确保玩家周围始终存在粒子碰撞,同时不会在视线之外或太远的区域浪费性能。

带符号距离场(SDF)碰撞

粒子碰撞带符号距离场(SDF)

节点列表中的 SDF 碰撞

SDF 碰撞节点会创建一个粒子可以碰撞的带符号距离场。SDF 碰撞与高度场碰撞类似,都是将其范围内的多个网格转化单一粒子碰撞体积。主要区别在于带符号的距离场可以表示孔洞、隧道和悬臂,而这是高度场无法做到的。与高度场相比,带符号距离场的性能开销较大,因此最适合中小型环境。

要创建 SDF 碰撞节点,添加一个新的子节点到你的场景,并从可用节点列表中选择 GPUParticlesCollisionSDF3D。SDF 碰撞节点必须经过烘焙才能对关卡中的粒子产生任何影响。为此,请在选中 SDF 碰撞节点时点击视口工具栏中的烘焙 SDF 按钮,然后选择一个目录来存储烘焙数据。由于 SDF 碰撞需要在编辑器中烘焙,因此它是静态的,无法在运行时更改。

SDF 粒子碰撞

SDF 粒子碰撞允许实现非常精细的三维碰撞形状

SDF 碰撞节点的形状像一个盒子。Extents 属性控制其大小。范围始终测量其边界边的一半,因此值 (X=1.0,Y=1.0,Z=1.0) 会创建一个各边宽 2 米的盒子。节点范围之外的任何内容在碰撞时都将被忽略。

Resolution 属性控制距离场的详细程度。较低的分辨率会以牺牲准确性为代价提高运行速度。如果分辨率太低,粒子可能看起来像是穿透了关卡几何体或在碰撞事件期间卡在空中。它们还可能完全忽略一些较小的网格。

分辨率比较

不同分辨率的带符号距离场覆盖会覆盖一片相同区域:16(左)和 256(右)

厚度``Thickness``属性赋予距离场(通常内部是空心的)一定的厚度,以防止粒子高速穿透。如果发现有些粒子没有与场景中的几何体发生碰撞,而是直接穿透了它们,请尝试将此属性设置为更高的值。

烘焙遮罩``Bake Mask``属性控制烘焙带符号距离场时将考虑哪些网格。只有在烘焙遮罩的活动图层上渲染的网格才会参与粒子碰撞。

故障排除

为了使粒子碰撞起作用,粒子的可见性 AABB 必须与碰撞器的 AABB 重叠。如果尽管设置了碰撞器,但碰撞似乎不起作用,请通过选择 GPUParticles3D 节点并在 3D 编辑器视口顶部选择 GPUParticles3D > 生成可见性 AABB… 来生成更新后的可见性 AABB。

如果粒子移动得很快而碰撞体很薄,有两种解决方案:

  • 让碰撞体变得更厚。例如,如果粒子不能穿过一个坚实的地面,你可以让代表地面的碰撞体比其实际的视觉表现更厚。高度图碰撞体(heightfield collider)在设计上自动处理这种情况,因为高度图无法表示“房间之上还有房间”的碰撞情况。

  • 增大 GPUParticles3D 节点中 Fixed FPS 的值,以增加粒子碰撞检测的频率。这会产生性能影响,所以应避免设置过大的值。