shader中使用模型坐标参与计算,就得注意批处理的影响,比如在场景中某个材质的物体出现一个的时候,表现正常,但是一旦再出现第二个,两个物体的表现就变成玄学了(不是自己预期的那样),一旦由隐藏掉另外一个,剩下的另一个由正常了。当然这肯定不是玄学,得分析分析其中的原因。

做一个简单的测试,使一个正方体上半部分显示绿色,下半部分显示红色:

UnityMain 于动态链接库错误_模型坐标


shader中在fragment中通过模型坐标Y的大小来决定颜色是红是绿:

fixed4 frag (v2f i) : SV_Target
{
    if(i.modelPos.y < 0){
        return fixed4(1,0,0,1);
    }
    else{
        return fixed4(0,1,0,1);
    }
}

此时拷贝一个同样的立方体,尝试修改position,神奇的事情发生了:

UnityMain 于动态链接库错误_shader_02


不是代码已经说好了,只是上面一部分是绿色下面是红色吗,怎么这个全绿了,额,这只是异常表现的一种情况,那么简单的几行代码,颜色值一定没有错是红与绿(没有鲤鱼和驴),那么问题一定处在了if判断那里,就是 i.modelPos.y不是我们想的那样(内置立方体y的坐标是-0.5与0.5)。打开FrameDebug可以清楚的看到,原来两个正方体已经被进行了动态合批处理DynamicBatch原本一个立方体24个顶点,而在渲染过程中将两个立方体网格合成了一个大的网格48个顶点。那么既然网格已经进行了合并,新网格上顶点的模型坐标也就不再是之前的模型坐标了,所以在执行之前的代码逻辑得到的结果就大概率不是预期结果。

UnityMain 于动态链接库错误_模型坐标_03

解决办法:

1.在设置中关闭Unity的动态合批(如果没有开启这个选项,那么也就不会遇到这样的情况了)

在PlayerSettings中能找到一个DynamicBatching的选项,取消掉勾选即可

UnityMain 于动态链接库错误_UnityMain 于动态链接库错误_04


不过虽然能解决当前这个问题,但是想到DynamicBatching能省下不少DrawCall,而且还是自动进行!所以不推荐这个做法。

2.正解:在Shader中添加tag关闭当前材质的动态合批属性
"DisableBatching" = "true"

Tags 
{ 
    "RenderType"="Opaque" 
    "DisableBatching" = "true" //这里记得加上这个标记
}

添加上这个Tag后,结果正确了

UnityMain 于动态链接库错误_unity3d_05