Unity Dynamic Occlusion导致的剔除问题

如果你的项目烘焙了遮挡剔除,那么可能也观察到了这种现象

一个动态的游戏物体,并没有勾选被遮挡体静态,但是他却会被静态物体遮挡

原本我理解的是如果没有勾选被遮挡体静态,那么这个物体应该不参与遮挡剔除的计算

后来查阅Unity对遮挡剔除的描述时,里面提到了一个DynamicOcclusion选项

真相大白

对动态游戏对象使用遮挡剔除 - Unity 手册

对动态游戏对象使用遮挡剔除

如果游戏对象是静态的,则 Unity 可以将这个游戏对象作为静态遮挡物 (Static Occluder) 和/或静态被遮挡物 (Static Occludee) 烘焙到遮挡剔除数据中。如果游戏对象是动态的,这个游戏对象可以在运行时充当被遮挡物,而不能充当遮挡物。

要确定动态游戏对象是否充当被遮挡物,可以在任何类型的渲染器组件上设置 Dynamic Occlusion 属性。启用 Dynamic Occlusion 后,渲染器在摄像机的视图中被静态遮挡物 (Static Occluder) 阻挡时,Unity 会剔除渲染器。禁用 Dynamic Occlusion 后,渲染器在摄像机的视图中被静态遮挡物 (Static Occluder) 阻挡时,Unity 不会剔除渲染器。

默认情况下会启用 Dynamic Occlusion。为了获得特定的效果,例如在墙后的角色周围绘制轮廓,可能需要禁用 Dynamic Occlusion。

如果确定 Unity 绝对不应该将遮挡剔除应用于特定的游戏对象,则可以禁用 Dynamic Occlusion 以减少运行时计算并降低 CPU 使用率。虽然这些计算对每个游戏对象的影响很小,但如果规模足够大,减少这些计算可能有利于提高性能。

Unity默认会开启MeshRedner上的DynamicOcclusion,进而导致这种现象

解决方案

这里还是建议默认开启,如果在游戏运行时发现有物体被不正常剔除了,再手动去关闭MeshRender上的DynamicOcclusion即可

Unity AABB盒导致的剔除问题

如果你的项目中有一些涉及到较大变形的蒙皮网格,你可能也观察到了这种现象

一个蒙皮网格,他明明在我的视线范围内,但是却被剔除了

原因就是Unity的视椎体剔除是按照物体的AABB盒来进行剔除的,默认情况下,Unity 不会更新对摄像机不可见的蒙皮网格。当网格返回屏幕时,Unity 会再次更新蒙皮。这样可以节省系统资源。

也就是说,如果我现在有一个球体,他默认的半径为0.5米,但是我通过蒙皮动画让他的半径膨胀到了10米,此时,他的AABB盒还是原本的大小,如果这个原本大小的AABB盒离开了我的视椎体范围,这个变大了的半径10米的球体还是会消失,而此时这个膨胀的球体实际上还是在我的视线范围内的,就会观察到球的突然消失

解决方案

  1. 将AABB盒加大

    每一个MeshRender上都会有一个Bounds属性,这就是他对应的AABB盒,可以点击EditBounds来设置他的大小

    image-20241009112643898

  2. 勾选UpdateWhenOffscreen
Update When Offscreen启用此选项可计算每帧的包围体积(即使对摄像机不可见)。禁用此选项可在游戏对象不在屏幕上时停止运行动画。 默认情况下,Unity 不会更新对摄像机不可见的蒙皮网格。当网格返回屏幕时,Unity 会再次更新蒙皮。这样可以节省系统资源。有关更多信息,请参阅下面的确定游戏对象的可见性

确定游戏对象的可见性

Unity 使用网格的 Bounds 属性来确定游戏对象是否可见。也就是说,整个包围体积必须在所有激活的摄像机的视野之外。但是,动画网格的真实包围体积可能随着动画的播放而变化(例如,如果角色将手举到空中,则包围体积会变高)。Unity 在计算最大包围体积时会考虑所有附加的动画,但有时无法通过计算包围体积边界来预测每个可能的用例。

以下每个示例情况在 Unity 将骨骼或顶点推出预先计算的包围体积时都可能出现问题:

  • 在运行时添加的动画
  • 附加动画
  • 使用程序从脚本中更改骨骼的位置
  • 使用的顶点着色器可将顶点推到预先计算的包围边界之外
  • 使用布娃娃

在这些情况下,可以尝试使用以下任一解决方案来解决问题:

  • 修改 Bounds 的值以匹配网格的潜在包围体积。

    尽可能使用此选项,因为它对性能更有利。

  • 启用 Update When Offscreen 以始终进行蒙皮和渲染蒙皮网格。

    如果性能不是主要问题,或者如果无法预测包围体积的大小(例如,使用布娃娃时),则可使用此选项。

为了使蒙皮网格在使用布娃娃时有更好的表现,Unity 会在导入带蒙皮的网格渲染器时自动将其重新映射到根骨骼。但是,仅当模型文件中只有一个带蒙皮的网格渲染器,Unity 才会执行此操作。如果使用布娃娃,并且无法将所有带蒙皮的网格渲染器附加到根骨骼或子项,则应关闭此优化。

最后修改:2024 年 10 月 09 日
如果觉得我的文章对你有用,请随意赞赏