在咱们的游戏场景中,有一个场景物件是由三个半透明面片组成的,他们三个使用的是同一个材质球,可是夹在中间的这个片美术用插件对它作了uv动画,一旦启动游戏就会实例化成为一个独立的材质球。在进行DrawCall检查的时候发现中间这层片一旦隐藏,就会致使下降2个DrawCall。最开始觉得是材质的问题,仔细看了Shader以后看不出什么端倪。把uv动画的物体换成内置Diffuse就行了,可是换成任何其它半透明的shader都会有问题。动画
就这样我跟这个问题鬼扯了一个多小时。直到某一次偶然手欠,挪了一下中间那个片片,DrawCall少了一个,我才一拍脑壳,恍然大悟。spa
欲知前因后果,且听我娓娓道来。插件
要渲染半透明物体,为了可以获得正确的渲染结果,对物体进行排序而且保证自后向前渲染是必须的。因此对于个人三个片片,引擎确定是先渲染最后面的那个片,再渲染中间的,再渲染最前面的。排序
批次合并的本质实际上是把材质彻底相同的物体集中在一块儿进行渲染,这样在渲染这几个物体过程当中就再也不须要更换材质,节省掉几回更换材质的开销。游戏
对于我例子中的状况,若是中间的片片不加uv动画,那它们就是三个材质彻底相同的物体,能够毫无疑问的被合并成为一个批次。图片
如今,中间的片片加了一个uv动画,它有了属于本身的材质,咱们的3个物体共有2个材质,彷佛剩下两个片片没受影响,依然能够在同一批次渲染?但其实不能了,由于从渲染顺序上讲,当渲染ObjA后须要渲染ObjB,此时材质球已经被切换掉了,再渲染ObjC还要切换一次材质。it
若是我把中间的片片移动一下位置,或者是隐藏掉它,让它再也不成为夹在中间的物体,那么剩下两个物体又可以从新合并批次了。class
由于内置的Diffuse Shader是一个不透明Shader。游戏引擎在处理不透明(或AlphaTest)物体时,老是会比半透明物体先渲染,而且由于不存在混合的问题,因此也不须要保证自后向前渲。因此它的位置虽然还夹在中间,可是渲染时机已经被移动到了第一个。原理
首先想到的方式是简单的移动,让它不夹在中间。但这个方法有一个缺陷,若是有不少组这样的物件摆在同一个场景中,就确定有带动画的物体夹在它们中间,批次仍是会被打破。渲染
因此我转而改变带动画物体材质的RenderQueue,原理和Diffuse Shader同样,这样全部其它物体依然可以合并批次。
不管是哪一种方法,我都没法作到让带uv动画的那个物体看起来被夹在中间了,只是对于我目前的需求来说,是能够接受的一个效果。
静态的修改材质球的RenderQueue可让物体更早或者更晚渲染,而无视它的空间位置。假设我把ObjB的RenderQueue增长了10,那么它就会看起来摆在全部其它RenderQueue未经修改的物体的最前面,不管你在正面看仍是背面看。若是你真的须要在两面看起来都是正确的,能够给ObjB添加一个组件,间隔固定的时间判断玩家摄像机和它的相对位置。根据玩家摄像机在它的前面仍是后面,动态的决定把RenderQueue增长仍是减小,就能够了。