使用unity内置的批处理功能可以起到很好的性能优化效果。
批处理分为静、动态两种
【静态批处理 Baches Static】
静态批处理效果最好条件要求最简单,但要注意被标记为静态批处理的物体不允许改变位置。由于光照bake的原因,也会导致静态物体的阴影信息会烘焙到受影响的物体贴图上,所以从效果上也不应该再被移动。
【使用条件&步骤】
- 首先必须确定相同批次目标物体的Mesh Filter组件的Mesh必须相同
- 点击目标物体,在Inspector窗口勾选Static。
【使用动态批处理(Baches,Saved by batching)】
然而真实情况下我们并不能把所有物体都设置成静态,这时候就需要使用动态批处理了。动态批处理是满足条件后自动触发的。
【使用条件&步骤】
- 相同批次目标物体的Mesh Filter组件的Mesh必须相同。如果不是多个相同模型,则批处理无意义。
- 模型顶点数点必须小于900。
- 如果着色器同时使用顶点位置、法线、UV值三种属性则模型顶点数必须小于300。如果着色器同时使用顶点位置、法线、UV0、UV1、切向量五种属性则模型顶点数必须小于180。
- 不能进行缩放 Scale。每次调整模型的大小都会产生新的Batch。
- 不能修改材质。每次修改材质都会产生新的Batch。
- 不能使用lightmap(烘焙光照贴图),除非是先烘焙,后实例化物体。
- 多通道的shader会阻止批处理操作。unity自带的shader机会都包含多pass。只有unlit等是单pass的
- 关闭 Mesh Renderer组件 > Lighting 中的 Cast Shadows。 开启该选项会导致贴图变化,从而影响批处理形成。
- 需要shader支持Gpu instancing 。如果是unity自带的材质,直接勾选 “Enable Gpu instancing”。如果是你自己写的shader,需要改造一下才可以。
10.这是我最新发现的。。如果shader中启用了几何着色器则批处理无效。几何着色器不支持该功能! - 最最新发现的,要注意尽量不调整材质设置中uv那里的4个数值。否则可能会使批处理失效,就算是一模一样copy的模型也不行!!!!
支持动态批处理的shader改造方法
改造方法:
- 预处理区添加宏:#pragma multi_compile_instancing
- 顶点着色器数据结构尾部添加 UNITY_VERTEX_INPUT_INSTANCE_ID
- 片元着色器数据结构尾部添加UNITY_VERTEX_INPUT_INSTANCE_ID
- 顶点着色器头部添加UNITY_SETUP_INSTANCE_ID(v); UNITY_TRANSFER_INSTANCE_ID(v,o);
- 片元着色器头部添加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
}
}
}