RoomManager
Inherits: Spatial < Node < Object
RoomManager 节点用于控制portal剔除系统。
描述
为了使用portal遮挡剔除系统,您必须使用 Room 和 Portal 来构建您的关卡。在这些可以在运行时使用之前,它们必须经过一个简短的转换过程来构建 room graph
,这是portal剔除所需的运行时数据。 portal graph
由RoomManager
节点控制,RoomManager
还包含整个portal系统通用的设置。
属性
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
process_priority |
| |
| ||
| ||
| ||
| ||
| ||
|
方法
void | rooms_clear ( ) |
void | rooms_convert ( ) |
枚举
enum PVSMode:
PVS_MODE_DISABLED = 0 —- 在运行时仅使用 Portal 来确定可见性。 Room的转换不会产生PVS,无法使用游戏通知。
PVS_MODE_PARTIAL = 1 —- 使用 PVS 和 Portal 的组合来确定可见性(这通常是最快和最准确的)。
PVS_MODE_FULL = 2 —- 仅使用 Room 的 PVS(潜在可见集)来确定可见性。
属性说明
- bool active
Default |
|
Setter | rooms_set_active(value) |
Getter | rooms_get_active() |
打开和关闭portal剔除系统。
需要注意的是,当portal剔除处于活动状态时,它负责 所有 3d 剔除。某些编辑器功能可能更难使用,因此切换活动标志旨在确保您的 Room / Portal 布局在编辑器中工作。
当room graph
被卸载(空间尚未转换)时,切换到active
将不起作用。
- bool debug_sprawl
Default |
|
Setter | set_debug_sprawl(value) |
Getter | get_debug_sprawl() |
大型物体可以“蔓延”超过一个以上的空间。该设置对于可视化那些蔓延在当前空间外的对象会很有用。
切换此设置可打开和关闭此调试视图。
- float default_portal_margin
Default |
|
Setter | set_default_portal_margin(value) |
Getter | get_default_portal_margin() |
通常我们不希望只有刚好跨越边界进入相邻Room的物体蔓延到那个空间。为防止这种情况发生,每个 Portal 都有一个额外的边距或容差区,物体可以在其中进入而不会蔓延到相邻的空间。
在大多数情况下,您可以在此处为所有portal设置此项。可以覆盖每个portal的边距。
- bool gameplay_monitor
Default |
|
Setter | set_gameplay_monitor_enabled(value) |
Getter | get_gameplay_monitor_enabled() |
使用部分或完整 PVS 时,游戏监视器允许您在漫游对象或空间进入或退出 游戏区域 时接收回调。游戏区域被定义为主要或次要 PVS。
例如,这些回调允许您减少对远离玩家的对象的处理,或者打开和关闭 AI。
您可以选择通过 _notification
函数接收回调作为通知,或作为信号接收。
NOTIFICATION_ENTER_GAMEPLAY
NOTIFICATION_EXIT_GAMEPLAY
信号:"gameplay_entered"
, "gameplay_exited"
- bool merge_meshes
Default |
|
Setter | set_merge_meshes(value) |
Getter | get_merge_meshes() |
如果启用,系统将在转换期间尝试合并 Room 内的相似网格(特别是在材质方面)。这可以显着减少渲染期间所需的绘制调用和状态更改的数量,尽管代价是降低了剔除粒度。
注意:此操作在转换过程中的运行时运行,并且只会在导出或运行的项目上运行,以防止意外更改场景和丢失数据。
- int overlap_warning_threshold
Default |
|
Setter | set_overlap_warning_threshold(value) |
Getter | get_overlap_warning_threshold() |
转换空间时,如果检测到空间之间有重叠,编辑器会警告您。重叠会干扰确定摄像机和物体所在的空间。根据您的level,少量是可以接受的。您可以在此处更改出现编辑器警告的阈值。没有其他副作用。
- int portal_depth_limit
Default |
|
Setter | set_portal_depth_limit(value) |
Getter | get_portal_depth_limit() |
portal渲染是递归的 - 每次通过较早的portal看到一个portal时,都会产生一些成本。出于这个原因,并为了防止无限循环的可能性,此设置对递归深度提供了硬性限制。
注: 使用Full
PVS 模式时不使用该值。
- NodePath preview_camera
Default |
|
Setter | set_preview_camera_path(value) |
Getter | get_preview_camera_path() |
Portal 剔除通常使用当前的 Camera / 多个Camera 进行操作,但是为了在编辑器中进行调试,您可以使用此设置来覆盖此行为并强制它使用特定的相机以更好地了解遮挡的内容剔除正在做。
- PVSMode pvs_mode
Default |
|
Setter | set_pvs_mode(value) |
Getter | get_pvs_mode() |
可选地,在转换期间,可以计算从每个空间可能可见的空间的潜在可见集 (PVS)。这可用于帮助动态门户剔除,或完全替代门户剔除。
在 Full
PVS 模式下,潜在可见空间内的所有对象都将被剔除,如果它们在视锥体内,则进行渲染。
- float roaming_expansion_margin
Default |
|
Setter | set_roaming_expansion_margin(value) |
Getter | get_roaming_expansion_margin() |
为了减少对漫游对象的处理,会在它们移动时扩展其 AABB。用扩展后的空间计算漫游对象所处的房间。下次移动时,如果该对象的精确 AABB 仍然位于扩展后的空间,则无须再次处理该对象,可以相当节省 CPU。
缺点是如果扩展得过多,该对象就可能意外蔓延到隔壁房间,在本该剔除的地方出现。
为了在高效漫游和精准剔除之间达到平衡,用户可以自定义扩展的距离。这个距离一般由房间、对象的大小以及移动速度决定。大多数情况下,默认值应该都能达到合适的效果。
- float room_simplify
Default |
|
Setter | set_room_simplify(value) |
Getter | get_room_simplify() |
在转换过程中,Room 内对象的几何形状,或自定义指定的手动绑定,用于生成 凸多边形绑定。
这个凸多边形在可见性系统中是 必需的,并且用于许多目的。最重要的是,它用于决定Camera(或物体)是否在Room内。凸多边形生成算法很好,但有时它会创建太多(或太少)的平面,无法很好地表示空间体积。
room_simplify
值可用于对该过程进行精细控制。它决定了如何相似平面才能将它们视为相同(并删除重复项)。该值可以设置在 0(无简化)和 1(最大简化)之间。
此处设置的值是所有空间的默认值,但如果需要,个别空间可以覆盖此值。
空间凸包在编辑器中显示为线框。
- NodePath roomlist
Default |
|
Setter | set_roomlist_path(value) |
Getter | get_roomlist_path() |
要使 Room 转换过程成功,您必须将 RoomManager
指向 Room 和 RoomGroup 的父 Node,我们将其称为 roomlist
(roomlist 不是一个特殊的节点类型,它通常只是一个 Room)。
- bool show_margins
Default |
|
Setter | set_show_margins(value) |
Getter | get_show_margins() |
当在编辑器中使用portal工具时,显示Portal的边界。
- bool use_secondary_pvs
Default |
|
Setter | set_use_secondary_pvs(value) |
Getter | get_use_secondary_pvs() |
当对象进入和退出游戏时接收游戏回调时,游戏区域可以由Room的主要PVS(潜在可见集)或次要PVS(主要PVS及其相邻的PVS)定义Room)。
有时使用次要 PVS 的较大游戏区域可能更可取。
方法说明
- void rooms_clear ( )
该方法会从portal graph清除所有转换数据。在卸载关卡、从关卡转换到关卡或返回主菜单时使用此选项。
- void rooms_convert ( )
这是整个portal剔除系统中最重要的功能。没有它,系统就无法运行。
首先,它遍历作为 room list
的节点(以及其中的 RoomGroup)子节点的每个 Room,并将其转换并添加到 room graph
。
这适用于遵循特殊命名约定的 Room 节点和 Spatial 节点。它们应该以前缀 ‘Room_‘ 开头,然后是您希望为空间命名的名称,例如‘Room_lounge’。这将自动为您将此类 Room 转换为 Room 节点。如果您想构建整个空间系统,这很有用,例如Blender,并在您处理关卡时多次重新导入。
转换将尝试将作为 Room 的子代和孙代的 VisualInstance 分配给空间。这些应该被赋予合适的 portal mode
(参见 CullInstance 文档)。默认的 portal mode
是 STATIC
- 运行关卡时不会移动的对象,通常是大多数对象。
转换通常会使用这些 VisualInstance(和 Portal)的几何形状来计算空间的凸多边形边界。这些边界将显示在带有线框的编辑器中。或者,您可以为任何空间指定手动自定义边界,请参阅 Room 文档。
根据定义,空间内的 Camera 可以看到空间内的所有其他东西(这是使用凸多边形的一个优势)。但是,为了从一个空间看到相邻的空间,您必须放置 Portal,它代表摄像机可以看到的开口,如窗户和门。
Portal 实际上只是专门的 MeshInstance。实际上,您通常会首先通过创建 MeshInstance,尤其是 plane
网格实例来创建portal。您可以在编辑器中移动平面以覆盖窗户或门口,正面朝空间外。为了让转换过程知道您希望此网格成为portal,我们再次使用特殊的命名约定。要转换为 Portal 的 MeshInstance 应以前缀 ‘Portal_‘ 开头。
您现在有一个选择 - 您可以将名称保留为 ‘Portal_‘,并允许系统自动检测最近的 Room 进行链接。在大多数情况下,这将正常工作。
另一种方法是手动指定要链接到的 Room,在portal名称后附加一个后缀,该后缀应该是您要链接到的空间的名称。例如,‘Portal_lounge’ 将尝试链接到名为 ‘Room_lounge’ 的空间。
这里有一个特殊情况——Godot 不允许两个节点共享相同的名称。如果您想手动将多个portal通向同一个空间怎么办?当然,它们都需要被调用,例如‘Portal_lounge’?
解决方案是通配符。在空间名称之后,如果您使用字符 ‘\‘,则该字符及其后的任何内容都将被忽略。因此,您可以使用例如 ‘Portal_lounge*0’、‘Portal_lounge*1’* 等。
请注意,已经转换为 Portal 节点(而不是 MeshInstance)的 Portal 仍然需要遵循相同的命名约定,因为它们在转换过程中每次都会重新链接。
建议您仅将对象放置在希望留在这些空间内的空间中 - 即 portal mode
是 STATIC
或 DYNAMIC
(不穿越 Portal)。 GLOBAL
和 ROAMING
对象最好放置在场景树的另一部分,以避免混淆。有关portal模式的完整说明,请参阅 CullInstance。