许多Unity开发者都曾花费大量时间来优化Unity UI,但是,大部分情况下对性能造成恶劣影响的罪魁祸首,只不过是Canvas UI元素上某个属性的小小改动。
在这种情况发生时,甚至是Unity UI性能分析工作也无法解决降帧问题,本文将分享相关的解决方法。
下面是我最近项目发生的问题。
为了将项目移植到Oculus Quest,我花费大量精力优化了多个UI面板。大部分工作是把Overdraw级别降低到可以接受的程度,从而确保GPU能够更好处理实际的3D渲染过程。
我用了一个月时间来进行项目的UI优化,并且取得了不错的进展。有些时候,优化效果非常好,GPU处理UI时几乎都没花时间。我使用的不透明UI着色方法弥补了大多数UI分层造成的Overdraw,UI分层指在其它元素上绘制的UI。
通过使用高度优化的混合UI系统,我让UI有效地遮蔽了UI后的3D元素,轻松避免了遮蔽部分的渲染工作。
然而,我的工作远未结束……
使用Unity Profiler性能分析器分析UI时,我注意到一个问题:CPU每帧在UI渲染上会使用1ms时间。
这对于只为整体游戏执行过程提供13ms时间预算的平台来说,使用的时间实在是太多了。除了UI渲染外,执行过程还包括:物理功能、游戏逻辑、3D渲染、输入处理、VR功能、联网功能等。
有的情况下,UI会对CPU性能有更大的影响。
UI可以优化为对GPU友好,但是这样不会直接转化为高效的GPU性能。
事实上,CPU和GPU在Unity UI渲染上有着完全不同的任务。因此,建议使用不同方法处理CPU和GPU的优化。
在经过更多UI性能分析后,我发现问题所在:UI会在每一帧都不断重新创建,也就是说,每帧都会进行画布重构过程。
这会造成每帧都要在CPU上消耗1ms处理UI……好伤。为什么Unity会这样做?我一直以为Unity会缓存UI画布。
其实我的想法也没错。Unity确实会高效缓存画布,确保构建过程只进行一次。然而,当改变了任意画布上UI元素属性时,例如:颜色和位置等,问题就出现了。