原理
游戏中的元素非常多,但是摄像机能看到的内容是有限的,并且有些元素会被另外一些元素挡住,例如城墙一类的,城墙后面的元素就会被它挡住。如果不进行处理的话,这些元素也会带来一定的开销,此时可以使用遮挡剔除技术来剔除掉这些被挡住的元素,只动态保留摄像机能看到的内容。
遮挡剔除

遮挡与被遮挡
属性 | 描述 |
Occluder Static | 在遮挡剔除系统中,将游戏对象标记为 |
Occludee Static | 在遮挡剔除系统中,将游戏对象标记为 |
Object
筛选器 | 描述 |
All | 全部 |
Renderers | 在 Hierarchy 窗口或 Scene 视图中选择一个 |
Occlusion Areas | 在 Hierarchy 窗口或 Scene 视图中选择一个 |
Bake
参数 | 描述 |
Smallest Occluder | 可以遮挡其他游戏对象的最小游戏对象的大小(以米为单位)。通常,要使文件最小且烘焙时间最短,应选择在场景中产生良好结果的最大值。 |
Smallest Hole | 摄像机可以看到的最小间隙的直径(以米为单位)。通常,要使文件最小且烘焙时间最短,应选择在场景中产生良好结果的最大值。 |
Backface Threshold | 如果需要减小烘焙数据的大小,Unity 可以在烘焙时对场景进行采样,并排除场景中可见遮挡物几何体所含背面超过给定百分比的部分。背面百分比很高的区域可能在几何体的下方或内部,因此不太可能是在运行时摄像机所在的某个位置。默认值 100 表示绝不会从数据中删除区域。值越小,产生的文件就越小,但可能会导致视觉失真。 |
Occlusion Culling 弹出窗口有两种模式:Edit 和 Visualization
Edit
设置 | 描述 |
View Volumes | 启用此选项后,Scene 视图将包含蓝线,这些蓝线显示遮挡剔除数据中的单元格。单元格大小受 Smallest Occluder 设置的影响:值越小,产生的单元格越多且越小,从而使精度提高并且文件增大 |
Visualization
Visualize 模式可让您从给定摄像机的视角预览遮挡剔除的结果。如果选择了某个摄像机,则预览与该摄像机相关。否则,预览与您在 Visualize 模式下选择的最后一个摄像机相关。
设置 | 描述 |
Camera Volumes | 启用此选项后,您会看到黄线,黄线指示 Unity 为其生成遮挡剔除数据的场景区域。这取决于场景几何体以及在场景中使用 Occlusion Areas 选项定义的任何视图体积 (View Volumes)。当摄像机在黄线之外时,Unity 不会执行遮挡剔除。还可以看到灰线,这些灰线指示摄像机当前位置所对应的遮挡剔除数据中的单元格以及当前单元格中的细分。Smallest Hole 设置定义了单元格内细分的最小大小:值越小,每个单元格产生的细分越多且越小,从而使精度提高并且文件增大。 |
Visibility Lines | 启用此选项后,您会看到绿线,这些绿线指示当前选择的摄像机可以看到的内容。 |
Portals | 启用此选项后,您可以看到一些线代表遮挡数据中单元格之间的连接。当前可见的入口是当前所选摄像机可以看到的入口 |
Occlusion Area


遮挡区域,在大型的场景中如未创建遮挡区域游戏组件时,Unity会自动在烘焙时候进行创建,可能产生大量不必要数据。
所以这里建议手动创建遮挡区域 (Occlusion Areas) 放置在场景中,从而定义摄像机可能处于的区域的视图体积
设置 | 描述 |
Is View Volume | 启用:Occlusion Area 将定义视图体积。 禁用:Occlusion Area 不会定义视图体积。 必须启用此属性才能使 Occlusion Area 生效。 |
遮挡与被遮挡事件
当发生遮挡剔除时,Unity会自动调用
gameObject.SetActive(false)方法,可以使用以下方法进行监听

using UnityEngine;
public class OcclusionListener : MonoBehaviour
{
// 隐藏状态
private void OnBecameInvisible()
{
Debug.Log($"隐藏 ---> {}");
}
// 显示状态
private void OnBecameVisible()
{
Debug.Log($"显示 ---> {}");
}
}// 相机脚本
using UnityEngine;
public class RotationCamera : MonoBehaviour
{
public float speed = 10f;
private void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
if (h < 0)
transform.Rotate(Vector3.down * Time.deltaTime * speed, Space.Self);
else if (h > 0)
transform.Rotate(Vector3.up * Time.deltaTime * speed, Space.Self);
}
}
















