查看原文
其他

Unity UI Profiling:你怎么敢破坏我的批处理?

Ruben Bonet Unity官方平台 2022-05-07

许多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元素属性时,例如:颜色和位置等,问题就出现了。


这意味着,按钮悬停效果等所有UI动画都会在你不知情的情况下损耗游戏性能。在发生UI属性变化时,Unity会进行画布重构,大幅影响游戏性能


Unity UI的画布重构会让Unity迭代画布上所有UI元素,从而生成Draw Call的优化列表,其中包含:顶点、颜色和材质等信息,而画布重构过程的时间真的很长。



了解到持续UI画布重构的影响后,我们会问:为什么会受到画布重构的影响?我要怎么进行处理?

 

为了回答这个问题,我花了5个多小时进行研究,并使用了Unity Profiler性能分析器。下面介绍整个过程。


发现问题

假设我们面前有一个奇怪的UI,它挡在玩家面前,阻止玩家看到后边的内容。


我使用Grid Layout Group网格布局组排列了350多张图片,画面如下图所示。



即使UI上有350多张图片,UI的渲染工作也不会有太大开销。UI中有2个不同的图片,所以这些UI内容通常使用2个Draw Call便可渲染。


通过在性能分析器发现,渲染这样的UI几乎不会对CPU造成任何开销。大多数时候,使用的时间为0.01ms以下,效率非常高。


下图是出现的峰值现象。



那么图表最后出现的CPU峰值是什么情况?


画布重构问题

Unity性能分析器图最后出现的是什么情况呢?UI的CPU开销在一秒内翻了不止一倍,真的非常奇怪。


请在下面的示例中找到两个区别,点击图片可以放大查看。


低开销的画布


画布重构


这是一个提示:下图红色部分是画布重构的开销



PostLateUpdate.UpdateRectTransform和UGUI.Rendering.UpdateBatches在这里非常显眼,它们的作用是什么?


UpdateRectTransform表示特定对象的Transform属性发生变化,因此Unity必须执行高开销的逻辑来保持外观的一致性。


而我们不知道是其中的一个属性还是所有属性发生变化,到底是一个对象还是多个对象发生变化,以及是哪些对象发生变化。


第二项开销是UpdateBatches,表示整个画布几何体都要进行重构,该过程常称为画布重构(Canvas Rebuild)。画布重构指Unity遍历所有画布层级来生成Draw Call的列表。


此时会计算所有元素的顶点、索引、颜色和UV,然后执行批处理过程,尽可能合并多个Draw Call,从而减少将其发给图形驱动程序的CPU开销。


现在我们知道了具体情况,但如何避免画布重构过程呢?是什么造成画布重构过程的?


小结

  • UI元素上的属性变化会把元素标记为“Dirty”(受污染的)。


  • UI元素可能完全是受污染的,也可能是部分受污染的,例如:顶点污染、布局污染和材质污染。部分污染状态的恢复过程使用较少开销。


  • 在任意元素标记为“Dirty”时,Unity会完全重构画布。


  • 画布重构对CPU的开销很大,避免该过程是优化的关键。


使用简单粗暴的方法找到起因

我们仍要寻找这个问题的答案:是什么造成UI画布重构


然而,没有方法可以快速找到造成重构的东西,特别是在画布层级较多的的时候。面,我将展示找到画布重构来源的简单粗暴方法。



1

保持性能分析器的录制状态

设置好筛选掉指标,专注于真正重要的部分:渲染、脚本和UI。注意观察基线,了解当前基线的开销,其中会包含高昂的画布重构过程。



2

禁用UI对象并进行对比

选中一组游戏对象,然后禁用它们,对比其与之前性能基准线的不同。如果基线的提升效果不明显,请继续禁用游戏对象,直到出现明显的性能提升。



3

找到修改属性的部分

现在,我们找到了触发画布重构的对象,但到底是什么在触发它们呢?是一个调整画布大小的脚本,还是一个是改变画布位置的动画?


我们可以右键单击RectTransform,然后按下Find References in Scene,继续寻找答案。一旦找到造成UI画布重构的起因后,我们要对它进行处理,例如:禁用动画或变换。


也许你提出质疑:那么如何在庞大的UI层级使用这个方法呢?这个方法速度不快,而且很麻烦。


使用庞大的UI层级本身就不是理想的方法,这种复杂而深度的层级会使画布重构的CPU开销变得非常高昂。我们有时会遇到嵌套式的大型UI层级,而它造成的最大影响是玩家的游戏体验。


虽然简单粗暴的方法有助于找到画布重构的起因,但是长远来看不适合使用。随着我逐渐擅长优化UI,我开发了一个工具来使游戏体验符合玩家的期待。


画布重构的性能分析


针对UI优化来强化性能分析器

我强调了UI画布重构的频率和影响程度,在我的游戏中画布重构占用了所有CPU预算的10%。


前面介绍了找到画布重构起因的简单粗暴方法,但技术大牛不会止步于这种容易出错的方法。你可以花上几天时间来避免画布重构,但在不经意间,这种情况又会出现。


如果正在进行VR开发,这种情况非常值得重视。我们完全不希望在世界空间UI中出现画布重构。如果无法避免这种情况,玩家可能会有非常糟糕的体验。


开发者想完全避免画布重构,但性能分析器无法给出具体信息,该怎么办?


我们可以让Unity性能分析器提供有用信息,了解是什么在影响UI性能。


我们可以强化Unity性能分析器的功能,方法是修改公开的Unity UI源代码。在得到源代码后,我们要找到发生画布重构的代码函数。然后只需要使用BeginSample和EndSample这两个Profiler API即可。


如果使用Unity 2019.1或更早版本,Unity UI源代码在Bitbucket代码库免费提供。我们可以根据指南来下载、安装和修改。


获取Unity UI源代码:

https://bitbucket.org/Unity-Technologies/ui/src/2019.1/


我的建议是使用新版Unity,至少版本是Unity 2019.2新版本Unity默认包含UI的源代码,因为UI系统现在属于资源包管理器的一部分,这样可省去许多麻烦。


下面是我发现了一些可以添加Profiling API调用的代码部分:

  • CanvasUpdateRegistry.cs:PerformUpdate函数

  • Graphic.cs:SetAllDirty函数

  • Graphic.cs:SetVerticesDirty和SetMaterialDirty等函数


性能分析的源代码


这个方法很实用,但对艺术家或设计师并不友好。因此我编写了一个小型开源的Unity扩展,以便你强化自己的Unity性能分析器。


下图是我自定义的Unity性能分析器增强工具。



该免费工具可以快速调整性能分析模式,从而确保游戏有最佳性能。


Unity性能分析器增强工具会在编辑器外部运行,能够有效取代在Android和其它平台上对UI进行性能分析的工具。


这款工具的操作只需两个按钮:

  • Buff my Unity Profiler(增强Unity性能分析器)

  • Nerf my Unity Profiler(削弱Unity性能分析器)


如果你要下载获取此工具,请发送“UI工具“到公众号后台。


小结 

本文我们学习了如何解决画布重构问题引发的性能问题,希望大家使用Rubén Torres Bonet大神的工具优化项目,让性能得到提升。


下载Unity Connect APP,请点击此处 观看更多Unity官方精彩视频,请关注“Unity官方”B站账户。


你可以访问Unity答疑专区留下你的问题,Unity社区和官方团队帮你解答:

Connect.unity.com/g/discussion


作者:Rubén Torres Bonet

来源:thegamedev.guru



推荐阅读

Unity UI性能优化技巧

Unity 2019.1的UIElements功能介绍

Unity性能优化的最佳实践

移动开发性能优化利器:Mesh Baker

在Unity应用中更安全地使用URL处理器和OpenURL

在Shader Graph中使用表面梯度框架合成法线贴图

运用Unity进行自动驾驶中的程序化生成

揭秘《Sherman》:使用Unity制作影视级光照效果


官方活动

 Unity X 创想家计划

「Unity X 创想家计划」是针对中国地区9-15岁青少年的编程教育计划,火热报名中~~[了解详情...


Asset Store黑色星期五资源大促

11月25日-12月2日,Asset Store最受欢迎的资源将进行5折大促,每日一款特惠插件3折优惠。[了解详情...



喜欢本文,请点击“在看”


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存