Unity遮挡剔除使用
参考
所有文本均引用至Unity官方文档
遮挡剔除
“遮挡剔除”过程可防止 Unity 为那些被其他游戏对象完全挡住(遮挡)的游戏对象执行渲染计算。
摄像机在每一帧中执行剔除操作,这些操作会检查场景中的渲染器,并排除(剔除)那些不需要绘制的渲染器。默认情况下,摄像机执行视锥体剔除,这一过程将排除所有不在摄像机视锥体范围内的渲染器。但是,视锥体剔除不会检查渲染器是否被其他游戏对象遮挡,因此 Unity 仍会浪费 CPU 和 GPU 时间进行在最终帧中不可见的渲染器的渲染操作。遮挡剔除将阻止 Unity 执行这些徒劳的操作。
何时使用遮挡剔除
要确定遮挡剔除是否有可能改善项目的运行时性能,请考虑以下事项:
- 防止无意义的渲染操作可以节省 CPU 和 GPU 时间。Unity 的内置遮挡剔除在 CPU 上执行运行时计算,这可能会抵消其节省的 CPU 时间。因此,当项目因过度绘制而具有 GPU 密集型特征时,遮挡剔除最有可能提高性能。
- Unity 在运行时将遮挡剔除数据加载到内存中。必须确保有足够的内存来加载此数据。
- 当场景中一些界限明确的小区域被实体游戏对象彼此隔开时,遮挡剔除的效果最好。一个常见的例子是通过走廊连接的房间。
- 可以使用遮挡剔除来遮挡动态游戏对象,但动态游戏对象不能遮挡其他游戏对象。如果项目会在运行时生成场景几何体,则 Unity 的内置遮挡剔除不适用于该项目。
对动态游戏对象使用遮挡剔除
游戏对象可以是静态的,也可以是动态的(非静态)。静态游戏对象和动态游戏对象在 Unity 的遮挡剔除系统中的行为不同:
- Unity 可以将静态游戏对象作为静态遮挡物和/或静态被遮挡物烘焙到遮挡剔除数据中。
- Unity 无法将动态游戏对象烘焙到遮挡剔除数据中。动态游戏对象可以在运行时充当被遮挡物,而不能充当遮挡物。
要确定动态游戏对象是否充当被遮挡物,可以在任何类型的渲染器组件上设置 Dynamic Occlusion 属性。启用 Dynamic Occlusion 后,渲染器在摄像机的视图中被静态遮挡物 (Static Occluder) 阻挡时,Unity 会剔除渲染器。禁用 Dynamic Occlusion 后,渲染器在摄像机的视图中被静态遮挡物 (Static Occluder) 阻挡时,Unity 不会剔除渲染器。
默认情况下会启用 Dynamic Occlusion。为了获得特定的效果,例如在墙后的角色周围绘制轮廓,可能需要禁用 Dynamic Occlusion。
如果确定 Unity 绝对不应该将遮挡剔除应用于特定的游戏对象,则可以禁用 Dynamic Occlusion 以减少运行时计算并降低 CPU 使用率。虽然这些计算对每个游戏对象的影响很小,但如果规模足够大,减少这些计算可能有利于提高性能。
遮挡剔除和场景加载
在运行时,无论打开了多少个场景,Unity 一次仅加载一个遮挡剔除数据资源。因此,必须根据计划是一次加载一个场景还是一次加载多个场景,从而以不同方式准备遮挡剔除数据。
一次加载一个场景
如果使用 LoadSceneMode.Single 一次加载一个场景,则必须分别按以下方式烘焙每个场景的遮挡剔除数据:
- 在 Unity Editor 中,打开需要烘焙遮挡剔除数据的单个场景。
- 烘焙场景的数据。Unity 会生成数据并将保存为 Assets/[场景名称]/OcclusionCullingData.asset。Unity 会将对此资源的引用添加到打开的场景中。
- 保存场景。
- 对每个场景重复步骤 1、2 和 3。
在运行时,按以下方式加载场景:
- 将场景加载为项目的默认场景,或者使用 LoadSceneMode.Single 来加载场景。如果有
ActiveScene
,则 Unity 会卸载ActiveScene
以及ActiveScene
的遮挡数据资源(如果有)。Unity 随后加载您的场景及其遮挡数据资源。
一次加载多个场景
如果使用 LoadSceneMode.Additive 一次加载多个场景,则必须按以下方式一起烘焙这些场景的数据:
- 在 Unity Editor 中,打开 Unity 将在运行时加载的场景组的第一个场景。该场景将变为
ActiveScene
。 - 以累加方式打开组中的其他场景,使所有这些场景同时在 Unity Editor 中打开。
- 烘焙所有场景的数据。Unity 会生成所有打开的场景的数据,并将其保存为 Assets/[
ActiveScene
名称]/OcclusionCullingData.asset。Unity 会将对此资源的引用添加到所有打开的场景中。 - 保存场景。
在运行时,按以下方式加载场景:
- 加载场景组的第一个场景作为项目的默认场景,或使用
LoadSceneMode.Single
来加载场景。如果有活动场景,则 Unity 会卸载活动场景以及活动场景的遮挡数据资源(如果有)。Unity 随后加载您的场景以及共享的遮挡数据资源。 - 根据需要,使用
LoadSceneMode.Additive
加载其他场景。如果 Unity 发现以累加方式加载的场景的遮挡数据与活动场景的遮挡数据相同,则遮挡剔除将按预期工作。
请注意,共享的遮挡数据资源的文件较大。使用较大的遮挡数据资源不会在运行时对 CPU 产生任何其他影响。
有关在 Unity Editor 中使用多个场景的更多信息,请参阅多场景编辑的相关文档。
Occlusion Area
使用Occlusion Area指定区域后,这并不代表其他区域就不会计算遮挡剔除,而是在Occlusion Area 中遮挡剔除的计算精度会更高.如果不指定Area,Unity将会根据物体的标签勾选情况自动创建,但这可能会导致不必要的大量数据
属性: | 功能: |
---|---|
Size | 设置遮挡区域 (Occlusion Area) 的大小。 |
Center | 设置遮挡区域 (Occlusion Area) 的中心。默认情况下,此设置为 0,0,0,位于盒体的中心。 |
Is View Volume | 如果启用此属性,遮挡区域 (Occlusion Area) 将定义视图体积。如果禁用此属性,遮挡区域 (Occlusion Area) 不会定义视图体积。必须启用此属性才能使遮挡区域 (Occlusion Area) 生效。 |
Occlusion Portal
遮挡入口 (Occlusion Portal) 可以是打开或关闭状态。遮挡入口关闭时,它将遮挡其他游戏对象。遮挡入口打开时,它不会遮挡其他游戏对象。
在场景中设置遮挡入口
- 选择场景中的合适游戏对象来充当遮挡入口。适合作为遮挡入口的游戏对象包括中型到大型的实体游戏对象(例如门)。
- 确保未将此游戏对象标记为 Occluder Static 或 Occludee Static。
- 将 Occlusion Portal 组件添加到游戏对象。
- 烘焙场景的遮挡数据。请参阅开始使用遮挡剔除以了解相关说明。
- 确保 Occlusion Culling 窗口、Inspector 面板和 Scene 视图均为可见状态。
- 在 Scene 视图中,将摄像机移至遮挡入口正前方的位置。
- 选择具有 Occlusion Portal 组件的游戏对象。
- 在 Inspector 窗口中,开启和关闭 Occlusion Portal 组件的 Open 属性。在 Scene 视图中,观察遮挡剔除的差异。
在运行时打开和关闭遮挡入口
使用脚本将 Occlusion Portal 组件的 open 属性设置为所需状态。
void OpenDoor() {
// Toggle the Occlusion Portal's open state, so that Unity renders the GameObjects behind it
myOcclusionPortal.open = true;
// Call a function that plays a door opening animation, or otherwise hides the GameObject
…
}
Occlusion Portal 组件参考
*属性:* | *功能:* |
---|---|
Open | 如果启用此属性,遮挡入口将打开并且不会遮挡渲染器。如果禁用此属性,遮挡入口将关闭并且会遮挡渲染器。 |
Center | 设置遮挡入口的中心。默认值为 0,0,0。 |
Size | 定义遮挡入口的大小。 |
Occlusion Culling 窗口
打开 Occlusion Culling 窗口的方法是导航到顶部菜单,然后选择 Window > Rendering > Occlusion Culling。
Occlusion Culling 窗口有 3 个选项卡:__Object、Bake__ 和 Visualization。除此之外,当 Occlusion Culling 窗口和 Scene 视图均可见时,Scene 视图中将显示 Occlusion Culling 弹出窗口。
Object 选项卡
网格渲染器的遮挡剔除窗口
在 Object 选项卡中,可以单击 All、Renderers 和 Occlusion Areas 按钮以筛选 Hierarchy 窗口的内容。
当 Renderers 筛选条件激活时,在 Hierarchy 窗口或 Scene 视图中选择一个渲染器,即可在 Occlusion Culling 窗口中查看和更改渲染器的遮挡剔除设置。
当 Occlusion Areas 筛选条件激活时,可以在 Hierarchy 窗口或 Scene 视图中选择一个遮挡区域,然后在 Occlusion Culling 窗口中查看和更改遮挡区域的 Is View Volume 设置。也可以单击 Create New Occlusion Area 以便在场景中创建新的遮挡区域。
Bake 选项卡
在 Bake 选项卡中,可以微调遮挡剔除烘焙过程的参数。请通过配置这些设置在烘焙时间、运行时数据大小和可视化结果之间找到平衡。
Set Default Parameters 按钮可将参数重置为默认值。
遮挡剔除检视面板 Bake 选项卡。
设置 | 描述 |
---|---|
Smallest Occluder | 可以遮挡其他游戏对象的最小游戏对象的大小(以米为单位)。通常,要使文件最小且烘焙时间最短,应选择在场景中产生良好结果的最大值。 |
Smallest Hole | 摄像机可以看到的最小间隙的直径(以米为单位)。通常,要使文件最小且烘焙时间最短,应选择在场景中产生良好结果的最大值。 |
Backface Threshold | 如果需要减小烘焙数据的大小,Unity 可以在烘焙时对场景进行采样,并排除场景中可见遮挡物几何体所含背面超过给定百分比的部分。背面百分比很高的区域可能在几何体的下方或内部,因此不太可能是在运行时摄像机所在的某个位置。默认值 100 表示绝不会从数据中删除区域。值越小,产生的文件就越小,但可能会导致视觉失真。 |
有关配置这些值的详细技巧,请参阅“其他资源”页面上链接的文章。
Bake 选项卡的底部是 Bake 和 Clear 按钮。单击 Bake 按钮可烘焙遮挡剔除数据。单击 Clear 按钮可删除之前烘焙的数据。
Visualization 选项卡
当 Visualization 选项卡可见时,如果在 Scene 视图或 Hierarchy 窗口选择一个摄像机,则 Unity 将更新 Scene 视图,从所选摄像机的视角显示遮挡剔除的效果。可以使用 Scene 视图中的 Occlusion Culling 弹出窗口来配置可视化设置。
Scene 视图中的 Occlusion Culling 弹出窗口
Occlusion Culling 弹出窗口有两种模式:__Edit__ 和 Visualization。可以使用下拉菜单在两者之间切换。
Edit 模式
设置 | 描述 |
---|---|
View Volumes | 启用此选项后,Scene 视图将包含蓝线,这些蓝线显示遮挡剔除数据中的单元格。单元格大小受 Smallest Occluder 设置的影响:值越小,产生的单元格越多且越小,从而使精度提高并且文件增大。 |
Visualize 模式
Visualize 模式可让您从给定摄像机的视角预览遮挡剔除的结果。如果选择了某个摄像机,则预览与该摄像机相关。否则,预览与您在 Visualize 模式下选择的最后一个摄像机相关。
设置 | 描述 |
---|---|
Camera Volumes | 启用此选项后,您会看到黄线,这些黄线指示 Unity 为其生成遮挡剔除数据的场景区域。这取决于场景几何体以及在场景中使用 Occlusion Areas 选项定义的任何视图体积 (View Volumes)。当摄像机在黄线之外时,Unity 不会执行遮挡剔除。 您还可以看到灰线,这些灰线指示摄像机当前位置所对应的遮挡剔除数据中的单元格以及当前单元格中的细分。Smallest Hole 设置定义了单元格内细分的最小大小:值越小,每个单元格产生的细分越多且越小,从而使精度提高并且文件增大。 |
Visibility Lines | 启用此选项后,您会看到绿线,这些绿线指示当前选择的摄像机可以看到的内容。 |
Portals | 启用此选项后,您可以看到一些线代表遮挡数据中单元格之间的连接。当前可见的入口是当前所选摄像机可以看到的入口。 |
有关遮挡剔除的其他资源
Unity 使用 Umbra 库来执行遮挡剔除。在以下文章中可以找到有关 Umbra 的更多信息,包括有关烘焙过程、遮挡剔除数据内部的数据结构以及 Umbra 执行的运行时操作的信息:
- Umbra 在 Gamasutra 上发表的这篇文章详细介绍了 Umbra 的工作方式:Umbra 的下一代遮挡剔除 (Next Generation Occlusion Culling by Umbra)
此 Unity 博客系列包含有关优化 Umbra 的指南。这个系列与 Unity 的旧版本相关,此后用户界面发生了变化,但核心原理仍然相同: