参考的博客
重要:
3、UGUI会在每帧渲染时,将相邻的,同材质,同贴图的对象进行合并(这里还有其它的限制,如:不能镜像,顶点属性个数不能超过900,不能跨Mask等,不过只要避开就好)
二、界面UI元素DC优化总结:
1、处理方案:
1)在不影响表现的前提下,同材质,同图集的CSprite,最好放在一起。
2)在不影响表现的前提下,文字最好也放在一起。
3)如果通过Control + D 复制的预设,缩放会有一点点的改变,要把这些缩放改变重设回来。
2、效果:
以门客界面为例,TexBg与TexHead是贴图,没有办法进行合并,ImgLvBg,ImgNameBg是CSprite,且图集都是用的Widget,它们连在一起,所以合并了,ImgKuang与ImgSpecial的图集是Servitor,且连在一起,所以,这两个也合并了,TxtName与TxtLv,用的是同一个Font字体,所以也合并在一起了。所以一个Render就省了三个DC,如果一个列表中有30个Render,一个界面就省了90个DC,所以,界面中元素较多的时候这种做法大有好处。
三、拼UI界面时的建议:
1、对于List,Canvas这种多Render的组件,一定要注意DC合并的处理,处理逻辑如上。
2、对于道具特效,最好参考上述降特效DC的做法,因为真的可以省非常多DC
- 批处理动态物体需要在每个顶点上进行一定的开销,所以动态批处理仅支持小于900顶点的网格物体。
- 如果你的着色器使用顶点位置,法线和UV值三种属性,那么你只能批处理300顶点以下的物体;如果你的着色器需要使用顶点位置,法线,UV0,UV1和切向量,那你只能批处理180顶点以下的物体。
- 不要使用缩放。分别拥有缩放大小(1,1,1) 和(2,2,2)的两个物体将不会进行批处理。
- 统一缩放的物体不会与非统一缩放的物体进行批处理。
- 使用缩放尺度(1,1,1) 和 (1,2,1)的两个物体将不会进行批处理,但是使用缩放尺度(1,2,1) 和(1,3,1)的两个物体将可以进行批处理。
- 使用不同材质的实例化物体(instance)将会导致批处理失败。
- 拥有lightmap的物体含有额外(隐藏)的材质属性,比如:lightmap的偏移和缩放系数等。所以,拥有lightmap的物体将不会进行批处理(除非他们指向lightmap的同一部分)。
- 多通道的shader会妨碍批处理操作。比如,几乎unity中所有的着色器在前向渲染中都支持多个光源,并为它们有效地开辟多个通道。
- 预设体的实例会自动地使用相同的网格模型和材质。
- 字符串连接的处理。因为将两个字符串连接的过程,其实是生成一个新的字符串的过程。而之前的旧的字符串自然而然就成为了垃圾。而作为引用类型的字符串,其空间是在堆上分配的,被弃置的旧的字符串的空间会被GC当做垃圾回收。
- 尽量不要使用foreach,而是使用for。foreach其实会涉及到迭代器的使用,而据传说每一次循环所产生的迭代器会带来24 Bytes的垃圾。那么循环10次就是240Bytes。
- 不要直接访问gameobject的tag属性。比如if (go.tag == “human”)最好换成if (go.CompareTag (“human”))。因为访问物体的tag属性会在堆上额外的分配空间。如果在循环中这么处理,留下的垃圾就可想而知了。
- 使用“池”,以实现空间的重复利用。
- 最好不用LINQ的命令,因为它们会分配临时的空间,同样也是GC收集的目标。而且我很讨厌LINQ的一点就是它有可能在某些情况下无法很好的进行AOT编译。比如“OrderBy”会生成内部的泛型类“OrderedEnumerable”。这在AOT编译时是无法进行的,因为它只是在OrderBy的方法中才使用。所以如果你使用了OrderBy,那么在IOS平台上也许会报错。
3.1
Mask
- Mask组件会占用两个DrawCall,一个在底下设置Stencil Buffer,一个在顶上还原Stencil Buffer,Mask下的子元素夹在中间
- 如果多个Mask绑定的Image组件,属于同一个Atlas,那么Mask之间的元素可以进行合并(包括Mask自己产生的2个DrawCall);否则不能合并
- Mask外的元素和Mask内的元素,无法合批。
- Mask完全裁剪的元素,依然占据DrawCall
- Hierarchy中被Mask分割的元素,可以正常合批
- Mask裁剪掉的部分还会影响其他元素的Depth计算,而它自己的也会受到其他元素的影响。即:裁剪掉到部分只是不可见,对Depth计算没有任何影响。
3.2
RectMask2D
- RectMask2D本身不占DrawCall
- RectMask2D之间无法合并DrawCall
- RectMask2D外的元素和RectMask2D内的元素,无法合批
- RectMask2D完全裁剪的元素,不再占用DrawCall,也完全不参与Depth计算
- 5Hierarchy中被RectMask2D分割的元素,如果Depth、Atlas与RectMask2D下的某元素相同,则无法合批。
- RectMask2D裁剪掉的部分,依然参与Depth计算
- 如果RectMask2D上绑定了Image,那么多个RectMask2D的Image如果属于同一个Atlas可以合并
解释下第5条,如果同一个图集上可合批的元素,在Hierarchy中被一个RectMask2D分割在上下两部分,那么这些元素的合批有可能被打断。什么情况下会被打断呢?用N代表要合批元素所在的层,如果RectMask2D中第N层的元素和外面要合批的元素属于同一个图集(Atlas),那么这个合批就会被打断。
- UI元素Z值不为0时,会被视为3D UI,不参与合批。父节点Z != 0,则下面的元素都无法合批了。
在 Canvas 的 Screen - space - camera 的时候
UGUI 渲染的顺序是根据离摄像机的远近来进行的,
然后再根据canvas来,进行从上到下进行渲染。
例如:
A 和 B, 来个canvas,A比较近,就先渲染 A,A下面的所有 UI 元素,都可以覆盖 B 的UI。不用管与摄像机的距离。
然后在 A 的子物体下面,从上到下进行渲染,不管它与摄像机的距离远近。
总结来说就是,先根据 与摄像机的远近,来判断,先渲染哪一个 canvas,然后在同一个canvas下面,从上到下,依次进行渲染。