在房间和入口中使用对象

通常,当您使用 Godot 时,引擎会以相同的方式处理您可以看到的所有对象(VisualInstance)。入口渲染器略有不同,因为它区分在您的游戏中具有的不同对象角色。它通过这种区分来定义 Room,并以最有效的方式渲染和处理。

入口的模式

如果你在检查器中查看,Godot 中的每个 VisualInstance 都是从 CullInstance 派生而来,你可以设置它的 PortalMode,这决定了对象在入口系统中的行为方式。

../../../_images/cull_instance.png

STATIC

对象的默认模式是 STATIC。静态物体是房间内的物体,在关卡的整个生命周期内不会移动。像地板、墙壁、天花板都是 STATIC 对象的良好候选。

DYNAMIC

动态模式适用于预期在游戏过程中移动的对象。但有一个限制,他们不能离开原来的房间。这些对象由系统非常有效地处理。可能的示例如移动平台和电梯。

ROAMING

漫游模式适用于可以在房间之间移动的对象。比如玩家和敌人这样的事物应该被标记为漫游。这些计算比 STATICDYNAMIC 模式更消耗,因为系统必须跟踪漫游对象在哪个房间内。

GLOBAL

全局模式适用于您根本不希望遮挡剔除的对象。比如主要玩家的武器、子弹和一些粒子效果之类的东西都是 GLOBAL 模式的理想选择。

IGNORE

忽略是一种特殊的模式,适用于在系统中基本上是自由的对象。手动界线( -bound )会自动转换为忽略入口模式。它们不需要在游戏过程中显示出来,但会保留在场景树中,以防你需要多次转换关卡(例如在编辑器中)。你也可以选择对那些只想在编辑器中显示的对象使用这个方法(当 RoomManager 不活动时)。

您是否应该将对象放置在房间内(在场景树中)?

STATICDYNAMIC 对象最好放在场景树中的房间内。系统需要知道他们在转换期间在哪个房间,因为系统假设它们永远不会改变房间。将它们放置在场景树中的房间内,以明确告知系统你想得到它们的位置。

自动放置

但是,为了便于使用,也可以将 STATICDYNAMIC 对象放置在场景树中房间的 外部 ,但还在 RoomList 分支内。系统将尝试自动放置物体到合适的房间。这在大多数情况下都有效,但如果有问题,请使用显式方法。尤其在处理内部房间时需要显式方法,房间对庞大的对象有一定限制。

../../../_images/freeform.png

请注意,如果您将 STATICDYNAMIC 对象放置在房间之外,它们将不会影响房间边界。如果您使用房间几何体来得到边界,桌椅可以放置在房间外。但是,墙壁和地板应明确位于场景树的房间分支内,以确保边界正确。

建议将 ROAMINGGLOBAL 对象保存在任何房间或 RoomList 之外的场景树的分支中。它们 可以 放置在房间内,但为了避免混淆,通常最好把它们放在自己的分支上。对 IGNORE 对象的放置没有限制。

对象生命周期

重要的是,要注意 STATICDYNAMIC 对象的生命周期与关卡的生命周期相关,即从调用 rooms_convert() 以激活入口系统和调用 ` rooms_clear()` 卸载系统。这是因为在转换阶段有相当多的预处理工作,以便有效地渲染它们。

因此,当入口系统处于活动状态时,你不应该尝试创建或删除 STATICDYNAMIC 对象。这样做会导致系统自动卸载,因为它处于无效的状态。然而,你可以自由地 show()hide() 这些对象。

因此,顺序应该是:

  • 加载您的关卡。

  • 放置任何 STATICDYNAMIC 对象。

  • 然后运行 rooms_convert() 在所有 STATICDYNAMIC 对象被添加到场景树 之后

属于 ROAMINGGLOBALIGNORE 的对象可以根据需要自由创建和删除。

蔓延

尽管用户通常可以忽略入口系统的内部结构,但他们应该意识到系统能够处理庞杂的对象,以至于对象最终会出现在一个以上的房间中。每个对象都有一个核心房间,但使用 AABB 或几何图形,系统可以检测对象何时穿过入口进入相邻房间(或多个房间)。这被称为蔓延

这意味着,如果一个物体的角落延伸到邻近的房间,但该物体的主要房间没有显示(例如,火车的末端在不同的房间),该物体将不会被剔除,仍然会被显示。只有当对象不存在于任何可见的房间时,才会被剔除。

入口边距

我们很难将物体准确地放置在房间的边缘,如果我们选择在入口被越过的那一刻将物体扩展到相邻的房间,即使是非常小的数量,就会出现不必要的扩展,而物体最终会在不是真正需要的时候被渲染。为了解决这个问题,入口有一个可调整的 margin,物体越过这个边距就不会被考虑到下一个房间。边缘在编辑器中显示为红色的半透明区域。

您可以在 RoomManager 中设置全局边距。如果您需要微调,可以在入口中覆盖此边距值。当您在检查器中编辑边距值时,应该会在 3D 编辑器视窗中看到边距更新。

包含在边界中

对大于单个房间的对象的支持有另一种作用。您可能不想在自动房间边界的计算中包含某些对象。可以在检查器中为单个对象打开和关闭此功能。参阅Cull Instance > Include In Bound

虽然蔓延非常适合大型移动物体,同时它也为您提供了更多的关卡设计余地。例如,您可以创建一个大型地形部分并将其存在于多个房间中,而无需拆分网格。

灯光

通常,灯光的处理与其他可视化实例一样。可以放置在房间里,会按照灯光的大小和方向扩展到邻近的房间。例外的是 DirectionalLight. 平行光没有源房间,影响 任何地方 。因此它们不应该被放置在房间中。由于平行光可能很消耗,所以在室内时最好将其关闭,参阅 RoomGroup 部分。

祝贺!您现在已经掌握了使用房间和入口所需的中阶技术,已经可以使用这些来制作游戏,虽然还有更多功能。