Static Batching(静态批处理)

  • 静态批处理 是一种 draw call batching 方法, 它组合不移动的网格以减少 Draw Calls。它将组合的网格转换为世界空间,并为它们构建一个共享顶点和索引缓冲区。然后,Unity 执行单个 Draw Call,该调用使用此组合网格一次绘制批处理中的所有对象。静态批处理可以显著减少绘制调用的数量。
  • 静态批处理动态批处理 更高效,因为 静态批处理 不会转换 CPU 上的顶点。有关静态批处理的性能影响的更多信息,请参阅 性能影响

使用静态批处理

  • Unity 可以在构建时运行时执行静态批处理。作为一般规则,如果在构建应用程序之前场景中存在游戏对象,请使用 Editor 在构建时对游戏对象进行批处理。如果在运行时创建游戏对象及其网格,请使用 运行时 API
  • 使用 运行时 API 时,您可以更改静态批处理根的转换属性。这意味着您可以移动、旋转或缩放构成静态批处理的整个网格组合。您无法更改单个网格transform 属性。
  • 注意:要使用运行时静态批处理,您还必须将网格设置为启用 读/写

构建时的静态批处理

  • 您可以在 Editor 中启用构建时的静态批处理。
  • 要在构建时执行静态批处理:
    1. 转到 Edit > Project Settings > Player
    2. Other Settings (其他设置) 中,启用 Static Batching (静态批处理)
    3. Scene 视图或 Hierarchy 中,选择要批处理的游戏对象,然后在 Inspector 中查看它。
      • 提示:可以同时选择多个游戏对象,以便为所有游戏对象启用静态批处理。
    4. 在游戏对象的 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)使用动态批处理
  • 要对网格使用动态批处理:
    1. 转到 Edit > Project Settings > Player
    2. Other Settings (其他设置) 中,启用 Dynamic Batching (动态批处理)

网格的动态批处理

  • 网格的动态批处理的工作原理是将所有顶点转换为世界空间。在 CPU 上,而不是在 GPU 上。这意味着,当转换工作比执行 Draw Call 占用的资源更少时,动态批处理才是一种优化。
  • Unity 可以对阴影投射物使用动态批处理,即使它们的材质不同,只要 Unity 需要的阴影通道材质值相同即可。例如,多个 crate 可以使用具有不同纹理的材质。尽管材质资源不同,但差异与阴影投射物通道无关,Unity 可以在阴影渲染步骤中为 crate 游戏对象批处理阴影。

限制

  • 在以下情况下,Unity 要么根本无法使用动态批处理,要么只能在有限范围内应用动态批处理:
    1. Unity 无法将动态批处理应用于包含超过 900 个顶点属性( position(位置) , normal(法线) , color(颜色) , 和 texture coordinates(纹理坐标) )和 225 个顶点的网格。这是因为网格的动态批处理每个顶点都有开销。例如,如果着色器使用 顶点位置顶点法线 和单个 UV ,则 Unity 最多可以批处理 225 个顶点。但是,如果着色器使用 顶点位置顶点法线UV0UV1顶点切线,则 Unity 只能批处理 180 个顶点。
    2. 如果游戏对象使用不同的材质实例,则 Unity 无法将它们一起批处理,即使它们本质上相同。唯一的例外是 阴影投射物渲染
    3. 具有光照贴图的游戏对象具有额外的渲染器参数。这意味着,如果要批量光照贴图游戏对象,它们必须指向相同的光照贴图位置。
    4. Unity 无法将动态批处理完全应用于使用多通道着色器的游戏对象。几乎所有 Unity 着色器都支持前向渲染中的多个光源。为了实现这一点,他们为每个光源处理一个额外的渲染通道。Unity 仅对第一个渲染通道进行批处理。它无法对其他每像素光源的绘制调用进行批处理。

动态生成的几何图形的动态批处理

  • 以下渲染器会动态生成几何图形,例如粒子和线条,您可以使用动态批处理对其进行优化:
    1. Built-in Particle Systems
    2. Line Renderers
    3. Trail Renderers
  • 动态生成的几何体的动态批处理与网格的动态批处理不同:
    1. 对于每个渲染器,Unity 会将所有动态可批处理的内容构建到一个大型顶点缓冲区中。
    2. 渲染器设置批处理的材质状态。
    3. 然后,Unity 将顶点缓冲区绑定到 GPU。
    4. 对于批处理中的每个 Renderer,Unity 会更新顶点缓冲区中的偏移量并提交新的 Draw Call
  • 此方法类似于 Unity 提交 静态批处理Draw Call 的方式。

SRP Batcher

GPU Instancing