遮挡器节点

除了通过 房间和入口 实现遮挡外,Godot 还提供了使用简单几何 Occluder(遮挡器)节点进行简单遮挡的能力。这些几何体形状会在编辑器中以小工具的形式显示,在运行时不可见。

完全被该形状遮挡(位于背部或内部)的对象在运行时会被剔除。它们是以简单易用、不带来运行时负担为目的而设计的,但也因此可能没有 房间和入口 高效。然而,在某些情况下仍然会带来显著的性能提升。

备注

需要重点注意的是,几何体遮挡器的工作原理是检查遮挡器和被遮挡物体的轴对齐包围盒(AABB)。AABB 被完全遮挡才会进行剔除。因此,剔除较小的对象比剔除较大的对象更高效,较大的遮挡器通常比较小的遮挡器效率更高。

Occluder 节点的主要优势在于它们是完全动态的。例如你为宇宙飞船添加了遮挡器子节点,那么这个遮挡器就会跟随父对象移动。

Occluder 节点之所以对性能影响那么小,是因为引擎在运行时会根据当前 Camera 的视角动态选择最相关的遮挡器。也就是说, 你可以在一个场景里拥有上百个遮挡器,在同一时间,只有那个最相关的会被激活。

Occluder 节点自身就是 OccluderShape 资源的持有者,功能顾名思义。首先,在你的场景树中添加一个 Occluder 节点。

小技巧

你会看到一个黄色的警告三角形,表示在 Occluder 可以生效之前,你必须在检查器中为其设置一个 OccluderShape。

OccluderShapeSphere

球体是最简单快速的遮挡器之一,设置和摆放都很方便。缺点是球体往往只在特定的游戏关卡设计中有意义,更适用于地形和有机背景几何体。

添加 OccluderNode 并在检查器中新建 OccluderShapeSphere 后,点击检查器中的 OccluderShapeSphere 调出它的参数。

../../_images/occluder_shape_sphere_inspector.png

与很多 Node 节点不同,OccluderShapeSphere 可以在一个对象中存储多个球体。在引擎中更高效,也能让你的 SceneTree 场景树更清爽。你不必把所有的球体都保存在同一个 Occluder 里,管理起来会很麻烦,加 10 个左右的球体是比较合理的。这些球体非常轻量,而且通常加得越多越能与几何体相匹配。

为了保存多个球体,它们会被存入 Array 数组。你可以在检查器中点击 Array,然后把 Array 的大小增大,来添加一个球体。

../../_images/occluder_shape_sphere_terrain.png

编辑器窗口中,这个球体会显示为一个小小的粉色圆形物体。每个球体有两个句柄。中间较大的的句柄可以用来在 Occluder 的局部空间中移动球体,较小的句柄可以用来调整半径。

虽然你也可以通过在检查器中修改 Occluder 节点的变换属性来改变这个球体的位置,但是这样就会移动数组中的所有球体。如果你想在一个遮挡器中使用多个球体,请使用那些句柄来调整位置。因为要支持 3D 空间中的定位,小工具会根据编辑器的视点,只允许移动 3D 位置中的两个主轴。百闻不如一试。

小技巧

使用多个球体时,编辑器还提供了一个便捷的功能。如果你单击工具栏上的居中节点按钮,就会重新计算这些球体相对于整个节点的局部位置,然后修改 Occluder 节点的变换。这个功能可以让排布小球变得更方便。

在运行时,你可以通过修改 Occluder 节点的可见性来开关这些球体,这个节点也能进行移动、缩放、旋转等操作。

球体遮挡器的常见使用场景是为山体/丘陵地形提供遮挡。把球体放在山体内部,你就可以防止渲染山背面的树木、植物、建筑、对象等内容。如果发挥想象力,还可以把它们用于大型飞行器、星球等移动对象。

OccluderShapePolygon

多边形是通用的遮挡器,几乎在任何情况下都可以使用,可以迅速为大多数场景提供一定程度的遮挡剔除。

和所有几何体遮挡器一样,成功的关键是把它们变大。它们不必和渲染的几何体完全一致,很多情况下让它们超过渲染的几何体,(在不阻挡有效的视线的前提下)尽可能地大反而效果更好。背后的原因是,一般来说多边形只会剔除 AABB 完全被它们遮挡的对象。要剔除较大的对象,你就需要更大的遮挡器。

备注

和所有遮挡器一样,多边形是可以重叠的,很多情况下重叠起来效果更好(剔除位于边界的对象的几率更大)。

编辑与细节

遮挡器多边形是以顶点列表的形式编辑的,这个列表定义的是位于同一平面上的多边形。为了保证多边形位于同一平面,这些顶点是定义在 2D 空间,而不是 3D 空间中的。该多边形的朝向、位置、缩放是从该 Occluder 节点的变换中获取的。

../../_images/occluder_shape_polygon_inspector.png

如果你创建一个 Occluder 并为其添加一个 OccluderShapePolygon 资源,默认会创建 4 个起始点,组成一个矩形。如果你修改该 Occluder 节点的位置和旋转,就可以看到该矩形会跟着节点一同变化。在编辑器中选中该 Occluder 时,每个节点都会出现一个句柄。你可以点击并拖动这些句柄,让你的多边形与场景中的环境相匹配。

../../_images/occluder_shape_polygon.png

你并不限于 4 个顶点,你可以在检查器中对顶点进行添加和移除,不过请注意:

  • 编辑器会自动清理这些顶点,让它们组成凸多边形。如果你把某个顶点拖到了可能形成凹多边形的位置,那么这个顶点就会被忽略。

  • 一般而言,边越少(顶点也越少),多边形在运行时就越快。6 条边的多边形要花费 3 条边的多边形两倍的计算量。在大多数情况下,有 4 个顶点就不错了。

../../_images/occluder_shape_polygon2.png

空洞

现实世界的游戏关卡并不总是存在大片连续的需要遮挡的区域。墙上一般都有门窗,山洞会有入口,等等。有些情况下,我们需要围绕这种缺口放置若干个 OccluderShapePolygon,但 Occluder 多边形还有一个生活小妙招——它们可以有“空洞”。

在检查器里,你会发现多边形除了有一组顶点之外,还有一组“空洞”的顶点。如果你为你的多边形添加 3 到 4 个这样的顶点,你会看到编辑器中出现了一些更小的句柄。这些句柄可以和多边形句柄一样拖动,形成一个凸洞。

../../_images/occluder_shape_polygon_hole.png

空洞可以完全在多边形内部(例如窗户)、接近边界(类似门)、或者与某一条边相切,让整个遮挡器变成凹的。空洞的工作原理遵循以下简单的规则:

  • 如果要剔除的对象完全被多边形遮蔽,那么它就会去看是否可以透过空洞看到自己。如果该对象碰到了空洞,那么就不会被剔除,但如果是被多边形遮蔽并且无法透过空洞看到那么就会被剔除。

备注

相比于创建很多个比较小的 OccluderShapePolygon,添加空洞一般更加便捷,在运行时也更快更好。

空洞的限制

空洞的主要限制是每个多边形只能有一个空洞。如果你存在需要两个或更多的空洞的场景,你可以选择:

  • 把两个空洞的区域联合为一个较大的空洞(如果它们靠得比较近)。

  • 使用两个或更多的 OccluderPolygon。

小技巧

请记住,多个多边形是可以重叠的,你应该利用这一点。

需要多少 Occluder 多边形呢?

这很大程度上取决于你的场景,不过一般而言,从 3 到 4 个精心布置的多边形开始就可以获得不错的效果。在此之后,就完全取决于你打算花费多少时间了。遮挡器的放置可以算是一种艺术形式,用得越多,掌握得也就越好,也能从中学得新的技巧。

一些想法:

  • 在构建关卡时考虑遮挡。

这就是很多专业人士的秘密。好的关卡设计并不只是满足游戏性的需求,也应该同时考虑遮挡。

  • 在多层建筑中,可以试试在楼层之间放置一个多边形遮挡器,然后在楼层之间楼梯井的位置放一个空洞。这样就应该能够剔除整个楼层,大幅提升性能。

  • 不要害怕将你的多边形遮挡器延伸到可见几何体边界之外的地方,这样可以剔除更多的对象——例如一直延伸到地面或这天空之中。

动态地使用多边形

和所有几何体遮挡器一样,多边形并不局限于静态(不移动)的几何体,可以在移动的对象上放置。你甚至可以实时地改变顶点的相对位置。

一些规范:

  • 移动多边形是有较小的花费的,多边形顶点的变换每发生一次变化,都必须在 CPU 上进行变换。

不用太过于担心这些,即便是 CPU 也能对顶点进行比较快速的变换,一般而言多边形比渲染的几何体上的顶点要少得多。不过如果你想要为 10000 个同屏的飞船创建多边形遮挡器,那还是需要进行考量的。

  • 改变多边形节点的变换(例如移动父级对象)比改变顶点本身要轻量。请尽可能使用前者而不是后者。