大型游戏中UI优化的几个原则

2021-04-09 15:47发布

一般在大型重度游戏(比如MMO,MOBA,SLG,FPS)的制作中,由于游戏地形大,玩家多,界面多,性能的优化就是重中之重的工作,而UI的优化又是性能优化工作中很重要的一部分,如果UI的优化做好了,会对游戏整体性能的提升有很大的帮助。那么UI如何优化那?下面我们来详细说一下:

 一、图片的大小和格式规范

1.最好不要超过2048*2048

2.最好都是2n次方(128,256,512,1024,2048)

3.最好都是方的(1024*1024,512*512这样的,不要1024*512这样的)

要压缩,选以下格式:

美术刚开始作图的时候就讲明一些规范,省的美术返工:

1.能共用的图片就共用:比如窗口的底图,边框,按钮的底图,边框等。不要把上面的图片设计的非常繁复,窗口,按钮尽量设计成一样的。           

2.一些图片能用九宫格就用九宫格

   二、图集划分的粒度

     1.共用的common不能太大。

     2.一个功能一个图集 登录,背包,技能,角色,商店等。

 3.一同出现的最好一个图集,比如主界面一个图集。 

三、ABA的问题 

ABA问题就是如下的问题:

 

如上图所示,底图ImageA蓝色背景 使用A图集,中图ImageB鬼头图标 使用B图集,

上图ImageA战力文字  使用A图集。三张图片,两个图集,本来应该是2drawcall,但是因为两个使用相同图集的图片中间夹了一个别的图集的图片,打断合批了,所以是3drawcall(如下图,Batches就是drawcall,基本是2,加上UI3)

如果把中间的ImageB隐藏,发现Batches变成了3,一下少了2drawcall

 

  UI制作的时候一定要避免ABA的情况,想法变成AAB或者ABB这样的情况。

四、动静分离

   动静分离就是说同一个界面下的UI,可活动的元素(血条,蓝条,伤害数字,CD)放在一个Canvas下,不可活动的元素(人物头像,商城,和平,抽奖等按钮)放在另一个Canvas下。虽然两个Canvas打断了合批,但是却减少了网格的重建时间,总体上是有优化的。

为什么要避免网格重建那? 如果重建的网格过大,就会很卡。比多一个drawcall还卡。

假如同一个Canvas里面有100ImageCanvas将会把100个单独的Mesh合并成一个大的ShareMesh,用于渲染。

   如果刚好这100Image都是使用了相同的图片或者是同一个图集里面的图片,那么由于使用的Mesh只有一个(ShareMesh),假如UI元素非常多,ShareMesh可能有2M大小(这是一个比较极端的例子,实际上一般的ShareMesh都是几百K,出现这么大的ShareMesh本身就需要注意了),材质球都是同一个(内置的默认材质球),贴图也是同一张,所以得到的结果就是,DrawCall只有一个。

如果这个100Image是不会动的,合并ShareMesh没有太大的问题

    但是如果是上面的血条,蓝条,名字板,CD,文字聊天信息这些需要动的UI元素和其他UI元素合并同一个ShareMesh的,那么问题就来了,血条由长变短,顶点发生了改变,导致2M的整体ShareMesh也需要重新的生成顶点信息,并且整个ShareMesh重新渲染,这明显是得不偿失的。

 

   当然动态的UI还包括文字部分,其中TextUGUI产生顶点数量的重灾区,一个字符产生4个顶点,如果再加上Shadow则相当于又把Text复制了一遍产生8个,

   Outline则会将Text复制4遍产生20个顶点。所以ShadowOutline不但会产生额外的OverDraw外还会产生过多的顶点数,

   一定慎用,确实需要请选择用图片背景替代,其次选择相对较省的Shadow

五、动态图集

所谓动态图集,就是图集是在游戏运行过程中生成的,而不是在游戏制作阶段生成的。程序生成一张或n张较大的Texture图集(根据项目需求,可以设置Texture大小为1024*10242048*2048等等),Image加载进来的Texture不直接使用,而是将Texture信息按照一定规则和排列拷贝到这张Texture上,以达到nImage共用一张Texture,合并Draw Call的目的,同时Image销毁不用之后,Texture信息从大的Texture图集中移除,达到图集空间重复利用的目的。

什么时候需要打动态图集那?

我们先来看看静态图集的缺点:

1)如果某个界面只需要出现一个图集中包含的小图标(比如掉了一个物品,学会某种技能),这个小图片是包含在一个大的静态图集里的,那为了显示一个很小的图标,就得加载一个很大的图集,从而导致打开该界面很慢(由于加载大的图集)。

并且后期热更新的时候,如果修改或者添加一张图片资源,那么就意味着要更新整个图集的资源。

2、那打成多静态个图集那?这样只有一个图标的界面没问题了。有多个图标出现的界面就有问题了,加载的也多,drawcall也多,并且为了合并Draw Call不被打断,要小心地设置UI的层级,避免ABA问题造成合批被打断,操作复杂度就提高了。

 

  物品图标打了多个图集

一个界面显示多种物品图标

下面demo只是简单的演示一下动态图集的主要思路,图片分配算法也只是将大图片分成64x64的一个一个分区,每个分区采用引用计数开控制是否在使用图片,用于维护整个UI系统的话,这种算法并不适用,但是如果只是用于icon图标的话,由于icon图标是固定尺寸的,所以这套算法就很合适了。

动态图集的缺点:

当然动态图集也是有缺点的,

1、动态图集因为将图集的生成过程延迟到了游戏运行时,所以必然会比静态图集多了图集生成的成本,当然这也是可以优化的。

2、并且在目前的动态图集生成方案中,还没有出现公开的支持压缩的动态图集解决方案。

3、还有一点,静态图集由于图片在生成过程中是确定的,可以将分配算法做得很好,图集的利用率也能做到很高。动态图集由于图片是动态生成的,在游戏运行过程中也会动态的增减图片,类似操作系统的内存分配算法,图集必然会出现碎片,图集的利用率也不可能做得很高

 

    总之, 如果能把以上五个方面都做到了,那么UI的优化就不成问题。当然有的项目不需要都做到,做到其中几部分就可以了。也有的项目需要做的比 上面的还多。这都得具体问题具体分析,如果游戏中3D场景,人物,特效部分优化做的好,那么UI的压力就小点,如果3D部分优化的不好,那么UI的压力就大点,需要优化的东西就多些。