Unity UI 优化整理

2,562 阅读3分钟

参考:gameinstitute.qq.com/community/d… 是UGUI优化的关键 -- Unite2017嘉宾杨怀忠分享《UGUI深度优化》

透明渲染队列

容易被忽略的关键点:Unity UI 基础里,所有的渲染细节都是透明队列。
渲染透明和不透明的区别非常大。在透明队列中,是从后往前画的。并且含有混合的问题, 它对性能的影响非常大。建议:做UI尽量保证每一个像素不重合,但是这很难做到。这就是关于Overdraw的话题。UI的问题可能会有80%以上的情况都是Overdraw太高。我们希望每个像素只画一次,但是因为Overdraw的存在,我们可能画了十次甚至更多。这对它的填充率就要求很高了。

关于合批和重合批

Rebatching是多线程的,同样的游戏在不同手机上性能差距会很大。

对于Canvas,每个Canvas在画之前都要进行一个合批的过程。如果这个Canvas底下所有的UI元素每一帧都始终保持不变,我们只需要合批一次。意思即是合批之后会把这个结果保存起来,如果下面再画第二帧的时候,如果没有变化,就继续采用第一帧的。如果发生变化了,就重用Batching。如果有任何一个UI组件发生了变化,它发生了dirty之后就会触发重新合批。重新合批的过程非常复杂。简单来说:

根据深度关系进行排序:

如果一个Cnavas底下的层级关系非常复杂(很难合批),它的排序的性能消耗呈非线性的增长。 合批很容易被打断,比如A-B-A就是三个Batch,两个A本来可以被Batch,但是会因为中间加入一个不同的Batch而被打断。层级应该优化为A-A-B这样就会变为两个Batch。

覆盖关系

需要尽量避免上文提到的UI重叠。 如果有两个Button,他们重叠的话,这就是一个覆盖关系。

优化技巧

参考:gameinstitute.qq.com/community/d…

UI中避免使用SetActive()来显示隐藏UI元素

因为SetActive()会遍历这个实体上所有继承MonoBehavior的脚本,并调用OnEnable()和OnDisable()方法,产生大量GC。 例如: Image组件继承于MaskableGraphic,其中MaskableGraphic的OnEnable()和OnDisable()有大量计算,会产生GC。 如果被SetActive()的实体上组件越多,带来的消耗就越高。

尽量避免Mask,使用Mask至少增加连个Drawcall,并可能导致本可以Batch的元素无法Batch。

避免在UI树结构下频繁增加/删除UI对象,UI层级结构发生变化会引起整个Canvas UI顺序更新,特别是复杂的UI树结构。

避免频繁动态的更新UI元素的Vertex,Rect,Color,Material,Texture等属性,会引起Rebuild,重新提交顶点数据(非常耗性能)操作。

尽可能使用少的UI Material和贴图(使用图集),是的可以Batching。

相邻的UI元素,使用相同材质贴图的UI元素尽可能排在一起,便于合并。