《Unity3D高级编程之进阶主程》第四章,UI(七) - UI优化(一)

这篇我们来聊聊,优化UI的几种方法,UI动静分离,拆分过大的UI,UI预加载。

===

① UI动静分离。

什么是UI动静分离?

动指的是元素移动,或放大缩小频率比较高的UI,静就是静止不动的,或者说动的比较少的UI。

我们在做项目中,避免不了一些UI会动的而且是不停的动的UI元素,这些一直在动的UI元素就是UI性能的祸害。

那么为什么要将他们分离开来呢?

UGUI 和 NGUI一样,都是用模型构建UI画面的,在构建后都做了合并Mesh的有优化操作,不合并会导致无数drawcall进而导致GPU队列阻塞或消耗加大,游戏性能降低。

合并操作是有极大益处的,但问题在于UI元素一动就需要重新合并,将那些原本不需要重新构建的内容也一并重构了,导致原来合并Mesh的好事变坏事。

因此要将行动的UI元素和静态不动的UI元素分离开来,让合并的范围缩小,只合并那些会动的UI元素,因为他们重绘的频率比较高,而那些基本不动的UI元素就不让它们参与重新合并Mesh的操作了。

那么如何分离他们呢?

UGUI 和 NGUI都有自己的重绘合并节点,我们可以称它们为画板,UGUI是Canvas,NGUI是UIPanel。

以画板为节点进行拆分。把会动的UI元素放入专门为它们准备的合并节点上,而将静止不动的UI留在原来的合并节点上。

这样一来,当会动的UI元素来回移动缩放的时候,不再会重构静态部分的UI了。在实际项目中静态的UI元素占UI的数量比较多,而动态的UI元素只是小部分。动静分离后,减少了不少的CPU在重绘和合并时的消耗。

② 拆分过大的UI。

为什么要拆分过大的UI?

项目的制作过程是个比较长期的时间过程,在这个过程中UI的大小会随着项目时间的积累而不断扩大。

很多时候我们总是莫名其妙的感觉,‘怎么这个UI界面,前段时间还好好的,现在打开会变得如何缓慢呢?!‘。

随着项目的推进,UI经手的人越来越多,添加的功能也越来越多,有的甚至一个Prefab里,装着2-3个界面。它们在展示一个界面时时隐藏了其他的几个而已,最后导致UI过大,实例化,初始化时,消耗的CPU过大。我们需要想办法拆分这些,过大的UI界面。

如何拆分?

把隐藏的UI界面拆分出来,成为独立运作的界面,只在需要它们时才调用并实例化。其次,如果界面内容还是很多,我们可以把2次显示的内容拆出来。

什么是2次内容?打个比方,一个界面打开时会显示一些内容(例如动画),完毕后或者点击后才能看到另外的内容。这之后出现的内容视为2次显示内容,可以考虑拆分出来成为独立的界面,需要时再加载。

注意权衡加载速度与内存,过大的UI固然加载缓慢内存消耗大,但拆分成小个体时,如果小个体频繁加载和销毁,也同样会消耗过多CPU。如果加载和销毁过于频繁,我们可以使用后面介绍的优化方法,把它们存起来不销毁。

③ UI预加载。

为什么要进行UI的预加载?

我们在UI实例化时,需要将Prefab实例化到场景中,这期间还会有Mesh的合并,组件的初始化,渲染初始化,图片的加载,界面逻辑的初始化等程序调用,消耗掉了很多CPU。这导致了在我们打开某个界面时,出现卡顿的现象,就是CPU消耗过重的表现。

上面讲的拆分UI是一个方面,不过只能在一些冗余比较大的界面上做优化,而一些容易比较小,难以拆分的UI界面,就很难再用拆分的方法优化效果。甚至有的UI界面即使拆分后,任然会消耗很多CPU。因此我们使用UI预加载,在游戏开始前加载一些UI界面,让实例化的消耗在游戏前平均分摊在等待的时间线上。

如何进行UI预加载?

第一步,最直接的方法,在游戏开始前加载UI资源但不实例化,只是把资源加载到内存。这样当点击按钮后,弹出UI界面时就少了一点加载资源的时间,把CPU消耗重心放在了实例化和初始化上。

第二步,在第一种方法的基础上,打开界面时CPU还是消耗太严重,那么就将UI实例化和初始化也提前到游戏开始前。只是实例化和初始化后,对UI界面进行了隐藏,当需要他出现时,再显示出来,而不再重新实例化,当关闭时,也同样只是隐藏而不是销毁。这样一来在打开和关闭时,只消耗了少量CPU在展示和隐藏上。

现在项目大都使用 AssetBundle 来做资源,但也有部分使用 Unity3D 的本地打包机制,这些prefab在Unity3D中有Preload的功能,在平台设置里这个功能,可以把需要预加载的Prefab加入到列表中去。它会将这些Prefab在进入APP或者说打开应用展示LOGO界面时进行预加载。在APP初始化时,预加载了指定的Prefab,CPU消耗在启动页面上,对于使用Resources.Load接口的加载整体效果不错。

最后,所有的预加载,都会出现另一个问题,CPU集中消耗带来的卡顿。预加载并没有削减CPU,CPU消耗的总量并没有发生变化。总体需要加载的图片数是不变的,实例化的元素数不变,以及初始化程序需要消耗的时间也不变,所有消耗总量是不变的。我们只是把它们这些消耗分离了或者说提前了,拆分到了各个时间碎片里去,让人感觉不到一瞬间有很大的CPU消耗。所以如果我们将这些预加载,集中在了某个位置,比如全部集中在游戏开始前,或者进度条的某个位置,也同样会有强烈的卡顿感,因为CPU在这个点进行了集中的消耗。

· 书籍著作, Unity3D, 前端技术

感谢您的耐心阅读

Thanks for your reading

  • 版权申明

    本文为博主原创文章,未经允许不得转载:

    《Unity3D高级编程之进阶主程》第四章,UI(七) - UI优化(一)

    Copyright attention

    Please don't reprint without authorize.

  • 微信公众号,文章同步推送,致力于分享一个资深程序员在北上广深拼搏中对世界的理解

    QQ交流群: 777859752 (高级程序书友会)