关于Unity的SetPass
在 Unity 中,SetPass Calls(SetPass 调用) 是渲染管线中核心的性能指标之一,本质是 GPU 切换渲染状态(着色器 Pass、材质、纹理、渲染目标等)的次数,直接反映渲染效率的高低。下面从核心概念、影响因素、优化方法等维度全面解析:
一、核心概念:SetPass Calls 是什么?
Unity 的渲染流程中,每个材质(Material) 关联的着色器(Shader) 会包含一个或多个 Pass(渲染通道)。当 GPU 渲染一批物体时:
- 若物体使用的材质/Pass 与上一批完全一致,GPU 可批量渲染,无需切换状态;
- 若材质/Pass 不同,GPU 必须停止当前渲染,切换到新的渲染状态(即触发一次
SetPass Call),再继续渲染。
简单来说:SetPass Calls 次数 = GPU 切换渲染状态的次数,次数越多,GPU 空等(状态切换)的时间越长,渲染性能越差(尤其移动端/低配设备)。
二、SetPass Calls 的计算逻辑
Unity 编辑器的 Stats 面板(Game 视图右上角打开)可实时查看 SetPass Calls 数值,其计算规则:
- 每个独立的
Pass切换触发 1 次调用; - 即使是同一材质,若渲染目标(如 RenderTexture)、深度测试、混合模式等状态变化,也会触发新的调用;
- 批处理(静态/动态批处理)能合并相同状态的物体,减少调用次数。
示例:
- 场景中有 100 个使用相同材质/相同 Pass 的立方体:开启静态批处理后,SetPass Calls = 1;
- 场景中有 100 个立方体,50 个用材质 A,50 个用材质 B(同 Shader 不同 Pass):SetPass Calls = 2;
- 若 100 个立方体用 100 种不同材质:SetPass Calls = 100(性能极差)。
三、影响 SetPass Calls 飙升的常见原因
-
材质/Shader 碎片化
- 大量不同材质(即使仅纹理/颜色不同)、Shader 包含多个 Pass(如 ForwardAdd 用于实时光照);
- 示例:每个物体单独改材质颜色,导致材质实例化(Material Instance),失去批处理条件。
-
批处理失效
- 静态批处理:物体未标记为
Static、顶点数超过阈值(默认 300)、使用动态纹理(如 RenderTexture); - 动态批处理:物体顶点数超过阈值(移动端300,PC400)、使用非统一缩放(如 (2,1,1))、包含多子网格;
- SRP Batcher 未开启(URP/HDRP 专属优化)。
- 静态批处理:物体未标记为
-
渲染状态频繁切换
- 混合模式(Blend)、深度测试(ZTest)、模板测试(Stencil)变化;
- 渲染目标切换(如多次渲染到 RenderTexture);
- 光照变化(如实时光照数量多,触发 ForwardAdd Pass)。
-
UI 渲染(UGUI)
- UGUI 每个“不同材质/图集”的 UI 元素会触发 SetPass 调用;
- 示例:分散的小图集、每个 Text 用不同字体材质,导致 UI 的 SetPass Calls 暴增。
四、优化 SetPass Calls 的核心方法
1. 启用批处理(最核心)
| 批处理类型 | 适用场景 | 开启/优化方式 |
|---|---|---|
| 静态批处理 | 静止物体(建筑、道具) | 标记物体为 Static;PlayerSettings 中开启 Static Batching;合并静态物体的网格 |
| 动态批处理 | 动态小物体(粒子、小怪) | PlayerSettings 中开启 Dynamic Batching;控制物体顶点数(<300);统一缩放 |
| SRP Batcher(URP/HDRP) | 所有物体 | 开启 SRP Batcher(Project Settings → Graphics);Shader 按 SRP 规范编写 |
2. 减少材质/Shader 碎片化
- 材质复用:避免为每个物体创建独立材质,共用材质实例(仅修改属性时用
MaterialPropertyBlock,而非实例化材质);// 推荐:用 MaterialPropertyBlock 修改属性,不实例化材质 MaterialPropertyBlock mpb = new MaterialPropertyBlock(); renderer.GetPropertyBlock(mpb); mpb.SetColor("_Color", Color.Red); renderer.SetPropertyBlock(mpb); - 合并 Shader Pass:减少 Shader 中的 Pass 数量(如用 SRP 合并非光照 Pass);
- 使用图集(Atlas):将多个纹理合并为一张图集,减少材质切换(UI/3D 物体均适用)。
3. 优化渲染状态
- 统一渲染状态:尽量让物体使用相同的混合模式、深度测试规则;
- 减少实时光照:实时光照会触发 ForwardAdd Pass,优先用烘焙光照(Lightmap);
- 合批渲染目标:减少频繁切换 RenderTexture,批量渲染到同一目标。
4. UGUI 专项优化
- 合并 UI 图集:将所有 UI 图片合并到少量图集,避免每个图片一个材质;
- 简化 Text 材质:共用字体材质,避免每个 Text 单独实例化材质;
- 禁用不必要的 Canvas:Canvas 重建会触发额外的 SetPass 调用,非可见时禁用。
五、关键注意事项
- SetPass Calls 不是唯一指标:需结合
Triangles(三角面数)、Vertices(顶点数)、GPU Instancing综合分析; - SRP Batcher 优先级高于传统批处理:URP/HDRP 项目优先开启 SRP Batcher,其原理是按 Shader 分组渲染,而非按材质,能大幅减少 SetPass 调用;
- 移动端敏感:移动端 GPU 状态切换开销远高于 PC/主机,SetPass Calls 超过 200-300 可能出现掉帧,PC 可接受更高数值(但仍需控制)。
六、调试工具
- Stats 面板:实时查看 SetPass Calls 数值;
- Frame Debugger:逐帧分析渲染流程,定位触发 SetPass 调用的物体/材质;
- Profiler(Render 模块):深入分析渲染耗时,找到 SetPass 调用的性能瓶颈。
总结
SetPass Calls 是衡量 Unity 渲染状态切换效率的核心指标,优化的核心思路是减少 GPU 状态切换次数:通过批处理、材质复用、图集合并、统一渲染状态等方式,将 SetPass Calls 控制在合理范围(移动端 < 200,PC < 500),可显著提升渲染性能。