Unity 几种常见合批手段的要求

概述

合批(Batching)是 Unity 渲染优化的核心手段,目的是将多个绘制调用(Draw Call)合并为一个,减少 CPU 与 GPU 之间的通信开销。Unity 中常见的合批手段有四种:

  • SRP Batcher
  • GPU Instancing
  • 动态合批(Dynamic Batching)
  • 静态合批(Static Batching)

每种合批方式都有严格的前提要求互斥关系,理解这些是正确使用它们的前提。


1. SRP Batcher

原理

SRP Batcher 通过复用 CPU 端的 Material 数据缓冲区,让 GPU 在同一绘制循环中快速切换材质数据,而不需要重新绑定 Shader 和 Constant Buffer。适用于大量使用相同 Shader 变体但不同材质属性的渲染对象。

前提要求

要求 说明
渲染管线 必须使用 SRP (URP / HDRP / 自定义 SRP),Built-in Render Pipeline 不支持
Shader 必须编写兼容 SRP Batcher 的 Shader。所有材质属性要通过 CBUFFER 声明(SRP 核心库中的 Shader 默认满足)
Shader 变体 合批的对象必须使用同一个 Shader 变体(即 Shader 文件和 keywords 组合完全一致)
平台 所有支持 DX10+(SM 4.0+)的平台均可
开启 在 Project Settings > Graphics > SRP Batcher 中开启(默认开启)

不满足时的行为

如果某个 Material 使用了不兼容 SRP Batcher 的 Shader,该 Material 会回退到传统渲染路径,不会影响其他兼容对象的 SRP Batcher 合批。

与 GPU Instancing 的关系

互斥 。如果材质开启了 Enable GPU Instancing,Unity 会优先走 GPU Instancing,不会走 SRP Batcher。


2. GPU Instancing

原理

GPU Instancing 将多个相同 Mesh、相同 Material 的渲染实例打包为一个 Draw Call,数据以 Instance Buffer 形式传给 GPU,由 GPU 一次性绘制。适合大量重复物体如草、树、子弹、粒子等。

前提要求

要求 说明
Shader Shader 必须声明 #pragma multi_compile_instancing,并在顶点着色器中调用 UNITY_VERTEX_INPUT_INSTANCE_ID / UNITY_SETUP_INSTANCE_ID
Mesh 必须完全相同(同一个 Mesh 引用)
Material 必须使用同一个 Material 实例(同一个引用,而非属性相同)
批次数量 单个 Draw Call 的实例数量受 GPU 限制(通常 500~1023 个实例)
开启 Material Inspector 中勾选 Enable GPU Instancing

额外说明

  • 每个实例可以通过 MaterialPropertyBlock 传递不同的属性(如颜色、缩放等),但 MaterialPropertyBlock 的字段必须在 Shader 中声明为 UNITY_INSTANCING_BUFFER_START/END
  • 不支持LOD 组内不同 LOD 级别的合批(不同 LOD 模型不同,无法 Instancing)。
  • 如果 Mesh 使用 SkinnedMeshRenderer,需要额外的兼容处理(部分平台不支持)。

互斥关系

合批方式 是否兼容
SRP Batcher ❌ 互斥,开启 GPU Instancing 后不走 SRP Batcher
动态合批 ❌ 互斥
静态合批 ❌ 互斥,但物理上不太会同时使用

3. 动态合批(Dynamic Batching)

原理

Unity 在 CPU 端将多个小 Mesh 合并为一个大的 Vertex Buffer,然后一次性提交 GPU 绘制。Unity 会自动检测满足条件的渲染器在每帧进行合并。

前提要求

要求 说明
顶点数 单个 Mesh 的顶点数 ≤ 300,<=900个顶点属性(Shader 中如果使用了某些属性会增加顶点计算量,实际会更严格)
UV 通道 最多支持 UV 0 和 UV 1,如果使用 UV 2、UV 3 则无法动态合批
光照 如果使用多 Pass Shader(包含多个 ForwardBase/ForwardAdd Pass),动态合批会失效
材质 参与合批的物体必须使用完全相同的 Material(同一个引用)
变换 物体不能同时受多个缩放因子不一致的父级影响,Uniform Scale 环境下表现最佳
镜像变换 负缩放(Scale 为负数)会导致法线计算错误,动态合批会自动跳过

性能代价

动态合批是在 CPU 端每帧合并顶点数据 ,对于顶点数较多的物体反而会拖慢性能。因此它只适合少量小顶点物体(如粒子、小道具)。

互斥关系

合批方式 是否兼容
SRP Batcher 可以共存,但如果一个物体走动态合批就不会走 SRP Batcher
GPU Instancing ❌ 互斥
静态合批 ❌ 互斥,同一物体不会同时参与两者

4. 静态合批(Static Batching)

原理

构建时 (Build / Baking)将标记为 Batching Static 的物体合并到一个大的 Vertex Buffer 中,并生成统一的 Index Buffer。运行时直接作为一个 Mesh 提交绘制。

前提要求

要求 说明
Static 标记 物体必须勾选 Static 或单独勾选 Batching Static Flag
材质 参与合批的物体必须使用相同的 Material
移动 物体在运行时不能移动、旋转、缩放
内存 静态合批会创建合并后的大 Mesh,会显著增加 Build 后包体和运行时内存
顶点属性 不同 Mesh 可以有不同顶点格式,Unity 会自动补齐

注意事项

  • 静态合批会禁用 GPU Instancing(因为 Mesh 已经被合并了)。
  • 参与静态合批的物体仍然可以配合 LightmapOcclusion Culling 使用。
  • 如果场景中有大量重复物体(如路灯),静态合批后的 Mesh 无法利用 GPU Instancing,反而可能不如单独走 Instancing。

互斥关系

合批方式 是否兼容
SRP Batcher 可以共存。静态合批只是合并几何数据,渲染时仍走 SRP Batcher 管线
GPU Instancing ❌ 互斥。合批后的 Mesh 无法 Instancing
动态合批 ❌ 互斥。静态合批优先级更高

5. 合批对比总表

特性 SRP Batcher GPU Instancing 动态合批 静态合批
适用管线 URP / HDRP All All All
合批时机 运行时(GPU 端) 运行时(GPU 端) 运行时(CPU 端) 构建时
相同 Mesh 不需要 必须相同 不需要 不需要
相同 Material 不需要(相同 Shader 变体即可) 必须相同引用 必须相同 必须相同
顶点限制 ≤ 300
内存/CPU 开销 高(CPU 合并) 中(构建时增加内存)
运行时移动 可以 可以 可以 ❌ 不可以
与 SRP Batcher 兼容 --- ❌ 互斥 ✅ 共存但二选一 ✅ 共存
与 GPU Instancing 兼容 ❌ 互斥 --- ❌ 互斥 ❌ 互斥
推荐场景 大量不同材质但同 Shader 的对象 大量相同物体(草、树、子弹) 少量小顶点物体 完全静止的环境物体

6. 实际使用建议

  1. 优先使用 SRP Batcher(URP/HDRP 项目默认开启),它是最通用、约束最少、CPU 开销最低的方案。
  2. 重复物体用 GPU Instancing,尤其是草地、树木、弹壳、粒子等大量相同 Mesh 的场景。
  3. 动态合批只用于 UI 或极小物体,顶点数必须确认 ≤ 300,且不要跟 GPU Instancing 混用。
  4. 静态合批在老项目或 Built-in 管线中还有价值,但在 SRP 管线中已被 SRP Batcher 部分替代,且内存代价较高,需谨慎使用。
  5. 不要同时开启 SRP Batcher 和 GPU Instancing (同一材质会互斥),但可以同时开启 SRP Batcher 和静态合批
相关推荐
河南花仙子科技13 小时前
花仙子科技详解:小游戏合规开发完整要点
科技·游戏
旧物有情21 小时前
游戏开发常用架构 #MVP,MVC
游戏·unity·架构·mvc
笨鸟先飞的橘猫1 天前
游戏后端分布式学习——一致性协议Raft
分布式·学习·游戏
勇踏前人未索之境1 天前
Unity打包运行于鸿蒙手机
unity·智能手机·harmonyos
玖玥拾1 天前
Unity 3D 笔记(十一)UI 框架进阶:栈弹窗交互、BasePanel 基类虚方法、DoTween 界面动画
笔记·3d·unity
user-猴子1 天前
从零构建 2048 游戏,解析“Python-Use”范式的完整闭环
开发语言·python·游戏
爱自由的代码工1 天前
游戏买量预算怎么分配:核心逻辑、执行步骤与关键指标
游戏·游戏发行·游戏运营·游戏分发
郝学胜-神的一滴1 天前
中级OpenGL教程 023:Assimp模型加载全解——从源码到架构的骈文探秘
c++·unity·游戏引擎·cmake·unreal engine·opengl
爱自由的代码工2 天前
游戏沉默用户怎么激活?一套可执行的步骤、指标与复盘方法
大数据·游戏·游戏发行·游戏运营·游戏分发