
在Unity渲染优化中GPU Instancing和SRP Batcher它们解决的是同一个问题Draw Call太多导致CPU忙不过来降低CPU瓶颈、减少Draw Call。1. GPU Instancing同一个Mesh 同一个Material画N次只发1个Draw Call原理DrawCall 瓶颈主要来自 CPU 向 GPU 提交渲染状态、矩阵数据开销。 当场景有大量完全相同模型同一个 Mesh同一个 Shader只是位置、旋转、颜色不同CPU 只提交 1 次 Mesh 数据、1 次 Shader一次性把所有实例的变换矩阵、实例自定义数据颜色等打包成数组传给 GPUGPU 在顶点着色器循环遍历实例数组并行渲染成千上万个物体。传统方式N 个物体 → N 次 DrawCall GPU InstancingN 个相同物体 →1 次 DrawCall使用条件必须全部满足所有物体共用同一个 Mesh所有物体使用同一个 Shader并且 Shader 开启了 Instancing 支持#pragma multi_compile_instancing在材质面板勾选Enable Instancing实例数量不能超过 GPU 实例缓冲区上限一般几千优点极大降低 DrawCall适合海量重复物体草、树、碎片、粒子、敌人小怪集群不依赖 SRPBuilt-in 管线、URP、HDRP 都支持缺点Mesh 必须一模一样模型不同完全无法使用材质不能不一样实例数据缓冲区有上限实例过多要分批不适合零散、种类多的物体不能解决材质切换带来的 SetPassCall 开销。适用场景草地、树木、碎石、子弹、粒子替代物等大量重复静态/简单动态物体。数量越多收益越大几十上百个才值得开。2. SRP Batcher不同Mesh 兼容Material合并渲染状态切换减少SetPassCallSRP Batcher不合并 Mesh核心目标是减少SetPass 调用SetPassCall普通渲染每次切换材质 / ShaderCPU 要上传大量材质 Uniform 数据贴图、颜色、float 参数这就是 SetPass 开销SRP Batcher 的思路预先把兼容材质的 Shader 常量数据打包放到 GPU 的持久化常量缓冲区渲染时只要材质属于SRP 兼容材质CPU 不再重复上传材质的常量多个物体哪怕 Mesh 不一样只要材质兼容可以连续渲染大幅减少SetPassCall每个物体依旧保留自己的对象变换矩阵物体位置旋转矩阵还是会随物体提交。重点区分 SRP Batcher不会减少 DrawCall 数量它减少的是SetPassCallDrawCall 提交 MeshSetPassCall 切换材质 / Shader 状态。SRP 兼容材质要求Shader 必须是 SRP 管线原生 ShaderURP ShaderGraph / URP 手写 shader所有材质属性必须放到CBUFFER_START(PerMaterial)常量缓冲区不能使用很多旧的内置 Unity 变量部分旧内置全局常量会破坏兼容性不能使用 Material.SetXXX 在运行时频繁修改材质的属性会破坏 SRP 批打断合批坑运行时material.SetColor()会创建材质实例直接打断 SRP Batcher。如果要改属性用MaterialPropertyBlock不会破坏 SRP Batcher。优点Mesh 不需要相同不同模型只要材质兼容就能合批适用场景更广场景里大量不同模型共用一套材质减少 SetPass 开销对场景大量静态 / 动态物体都有效静态物体、动态物体都支持。缺点只能 URP/HDRPBuilt-in 管线没有 SRP BatcherShader 写起来有约束CBuffer 规范严格老 shader 很难直接兼容运行时直接修改 material 实例会打断批不会降低 DrawCallDrawCall 数量本身不变。最佳适用场景场景中大量不同Mesh但使用兼容Shader的物体如城市建筑、角色装备、UI元素。Draw Call数量高但单个Draw Call三角面数少的场景。几乎所有URP/HDRP项目都应默认开启Project Settings Graphics SRP Batcher。