使用unity内置的批处理功能可以起到很好的性能优化效果。
批处理分为静、动态两种

【静态批处理 Baches Static】

静态批处理效果最好条件要求最简单,但要注意被标记为静态批处理的物体不允许改变位置。由于光照bake的原因,也会导致静态物体的阴影信息会烘焙到受影响的物体贴图上,所以从效果上也不应该再被移动。

【使用条件&步骤】

  1. 首先必须确定相同批次目标物体的Mesh Filter组件的Mesh必须相同
  2. 点击目标物体,在Inspector窗口勾选Static。

【使用动态批处理(Baches,Saved by batching)】

然而真实情况下我们并不能把所有物体都设置成静态,这时候就需要使用动态批处理了。动态批处理是满足条件后自动触发的。

【使用条件&步骤】

  1. 相同批次目标物体的Mesh Filter组件的Mesh必须相同。如果不是多个相同模型,则批处理无意义。
  2. 模型顶点数点必须小于900。
  3. 如果着色器同时使用顶点位置、法线、UV值三种属性则模型顶点数必须小于300。如果着色器同时使用顶点位置、法线、UV0、UV1、切向量五种属性则模型顶点数必须小于180。
  4. 不能进行缩放 Scale。每次调整模型的大小都会产生新的Batch。
  5. 不能修改材质。每次修改材质都会产生新的Batch。
  6. 不能使用lightmap(烘焙光照贴图),除非是先烘焙,后实例化物体。
  7. 多通道的shader会阻止批处理操作。unity自带的shader机会都包含多pass。只有unlit等是单pass的
  8. 关闭 Mesh Renderer组件 > Lighting 中的 Cast Shadows。 开启该选项会导致贴图变化,从而影响批处理形成。
  9. 需要shader支持Gpu instancing 。如果是unity自带的材质,直接勾选 “Enable Gpu instancing”。如果是你自己写的shader,需要改造一下才可以。
    10.这是我最新发现的。。如果shader中启用了几何着色器则批处理无效。几何着色器不支持该功能!
  10. 最最新发现的,要注意尽量不调整材质设置中uv那里的4个数值。否则可能会使批处理失效,就算是一模一样copy的模型也不行!!!!
支持动态批处理的shader改造方法
改造方法:
  1. 预处理区添加宏:#pragma multi_compile_instancing
  2. 顶点着色器数据结构尾部添加 UNITY_VERTEX_INPUT_INSTANCE_ID
  3. 片元着色器数据结构尾部添加UNITY_VERTEX_INPUT_INSTANCE_ID
  4. 顶点着色器头部添加UNITY_SETUP_INSTANCE_ID(v); UNITY_TRANSFER_INSTANCE_ID(v,o);
  5. 片元着色器头部添加UNITY_SETUP_INSTANCE_ID(i);

以下面shader为例

Shader"Custom/myShader"{
	// 参数区
    Properties{
        ...
    }
    // shader区
    SubShader{
        Pass{
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // 1. 添加instancing 宏
            #pragma multi_compile_instancing
            struct a2v{
                // 参数...
                // 2. 在顶点输入结构的末尾添加,用于从gpu中获取instance id并传入顶点着色器
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
            struct v2f{
                // 参数...
                // 3. 在片元输入结构的末尾加入,用于将instance id传入片元着色器
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };
            v2f vert(a2v v){
                v2f o;
                // 4. 顶点着色器处理。 从输入结构体v中读取Instance_ID并输出给片元找着色器 
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_TRANSFER_INSTANCE_ID(v,o); 
                // 逻辑...
                return o;
            }
            fixed4 frag(v2f i):SV_Target{
            	// 5. 获取并处理instance id
                UNITY_SETUP_INSTANCE_ID(i); 
                // 逻辑...
            }
            ENDCG
        }
    }
}