Unity渲染优化的4种批处理
Static Batching(静态批处理)
静态批处理
是一种draw call batching
方法, 它组合不移动的网格以减少Draw Calls
。它将组合的网格转换为世界空间,并为它们构建一个共享顶点和索引缓冲区。然后,Unity 执行单个Draw Call
,该调用使用此组合网格一次绘制批处理中的所有对象。静态批处理可以显著减少绘制调用的数量。静态批处理
比动态批处理
更高效,因为静态批处理
不会转换 CPU 上的顶点。有关静态批处理的性能影响的更多信息,请参阅 性能影响。
使用静态批处理
- Unity 可以在构建时和运行时执行静态批处理。作为一般规则,如果在构建应用程序之前场景中存在游戏对象,请使用
Editor
在构建时对游戏对象进行批处理。如果在运行时创建游戏对象及其网格,请使用 运行时 API。 - 使用
运行时 API
时,您可以更改静态批处理根的转换属性。这意味着您可以移动、旋转或缩放构成静态批处理的整个网格组合。您无法更改单个网格的transform
属性。 - 注意:要使用运行时静态批处理,您还必须将网格设置为启用
读/写
。
构建时的静态批处理
- 您可以在 Editor 中启用构建时的静态批处理。
- 要在构建时执行静态批处理:
- 转到 Edit > Project Settings > Player。
- 在 Other Settings (其他设置) 中,启用 Static Batching (静态批处理)。
- 在
Scene
视图或Hierarchy
中,选择要批处理的游戏对象,然后在Inspector
中查看它。- 提示:可以同时选择多个游戏对象,以便为所有游戏对象启用静态批处理。
- 在游戏对象的
Static Editor Flags
中,启用Batching Static
。
- 如果指定的静态网格满足常见使用信息中描述的条件,则 Unity 会自动将指定的静态网格批处理到相同的
Draw Call
中。 - 注意:如果在构建时执行静态批处理,则 Unity 在运行时不会使用任何 CPU 资源来生成静态批处理的网格数据。
运行时的静态批处理
- 为了在运行时批处理静态网格,Unity 提供了
StaticBatchingUtility
类。静态StaticBatchingUtility.Combine
方法将您传入的游戏对象组合在一起,并为静态批处理做好准备。 - 与构建时的静态批处理不同,运行时的批处理不需要您启用
Static Batching Player Setting
。
性能影响
- 使用静态批处理需要额外的 CPU 内存来存储组合的几何体。
- 如果多个游戏对象使用相同的网格,则 Unity 会为每个游戏对象创建一个网格副本,并将每个副本插入到组合网格中。这意味着相同的几何体在组合网格中多次出现。
- 无论您使用的是
编辑器
还是 运行时 API 来准备用于静态批处理的游戏对象,Unity 都会执行此操作。 - 如果要保持较小的内存占用,可能必须牺牲渲染性能并避免对某些游戏对象进行静态批处理。例如,在茂密的森林环境中将树木标记为静态可能会对内存产生严重影响。
- 注: 静态批处理可以包含的顶点数存在限制。每个静态批处理最多可以包含
64000
个顶点。如果有更多,Unity 会创建另一个batch
。
Dynamic Batching(动态批处理)
- 动态批处理是一种
draw call batching
方法,可对移动的游戏对象进行批处理以减少Draw Calls
。动态批处理在Unity 运行时动态生成的网格
和几何体(例如粒子系统)
之间的工作方式不同(见下文)。
使用动态批处理
- Unity 始终对动态几何体(如 Particle Systems)使用动态批处理
- 要对网格使用动态批处理:
- 转到 Edit > Project Settings > Player。
- 在 Other Settings (其他设置) 中,启用 Dynamic Batching (动态批处理)。
网格的动态批处理
- 网格的动态批处理的工作原理是将所有顶点转换为世界空间。在
CPU
上,而不是在GPU
上。这意味着,仅当转换工作比执行Draw Call
占用的资源更少时,动态批处理才是一种优化。 - Unity 可以对阴影投射物使用动态批处理,即使它们的材质不同,只要 Unity 需要的阴影通道材质值相同即可。例如,多个 crate 可以使用具有不同纹理的材质。尽管材质资源不同,但差异与阴影投射物通道无关,Unity 可以在阴影渲染步骤中为 crate 游戏对象批处理阴影。
限制
- 在以下情况下,Unity 要么根本无法使用动态批处理,要么只能在有限范围内应用动态批处理:
- Unity 无法将动态批处理应用于包含超过
900
个顶点属性(position(位置)
,normal(法线)
,color(颜色)
, 和texture coordinates(纹理坐标)
)和225
个顶点的网格。这是因为网格的动态批处理每个顶点都有开销。例如,如果着色器使用顶点位置
、顶点法线
和单个UV
,则 Unity 最多可以批处理225
个顶点。但是,如果着色器使用顶点位置
、顶点法线
、UV0
、UV1
和顶点切线
,则 Unity 只能批处理180
个顶点。 - 如果游戏对象使用不同的材质实例,则 Unity 无法将它们一起批处理,即使它们本质上相同。唯一的例外是
阴影投射物渲染
。 - 具有光照贴图的游戏对象具有额外的渲染器参数。这意味着,如果要批量光照贴图游戏对象,它们必须指向相同的光照贴图位置。
- Unity 无法将动态批处理完全应用于使用多通道着色器的游戏对象。几乎所有 Unity 着色器都支持前向渲染中的多个光源。为了实现这一点,他们为每个光源处理一个额外的渲染通道。Unity 仅对第一个渲染通道进行批处理。它无法对其他每像素光源的绘制调用进行批处理。
- Unity 无法将动态批处理应用于包含超过
动态生成的几何图形的动态批处理
- 以下渲染器会动态生成几何图形,例如粒子和线条,您可以使用动态批处理对其进行优化:
- Built-in Particle Systems
- Line Renderers
- Trail Renderers
- 动态生成的几何体的动态批处理与网格的动态批处理不同:
- 对于每个渲染器,Unity 会将所有动态可批处理的内容构建到一个大型顶点缓冲区中。
- 渲染器设置批处理的材质状态。
- 然后,Unity 将顶点缓冲区绑定到 GPU。
- 对于批处理中的每个 Renderer,Unity 会更新顶点缓冲区中的偏移量并提交新的
Draw Call
。
- 此方法类似于 Unity 提交
静态批处理
的Draw Call
的方式。
SRP Batcher
GPU Instancing
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 SleepyLoser's Blog!
评论