Unity 手游性能蓝皮书 2017 - 2018

一、MMORPG手游总体性能开销分析

Android设备的CPU均值主体范围为17.775.5 ms,且主要集中在1733ms和33~50ms两档。

按照UWA官网的测评机型分类,我们将统计的性能数据分为低端、中端和高端;在趋势图中则直接以最具有代表性的低端和高端来展现。

  1. 大部分MMORPG手游在中低端设备的性能开销较高,大于33ms的耗时占比范围在60%~70%。
  2. 在过去的4个季度中,我们欣喜地看到了中国移动游戏在低端设备上的整体耗时出现了明显的下降趋势。这说明大家对于项目性能的把控越来越优秀!但在高端设备中,2018 Q2较之2018 Q1上升了3ms。这是因为在2018 Q2,超级重度的MMO手游开始陆续出现,其在高端设备上使用高精度的水体反射、大量的PBR材质和图像后处理,使得高端设备上的开销开始逐步上升。同时就目前看,超级重度MMO的出现还仅是开始,UWA推测其在高端设备上的开销将持续升高。

无论是高、中和低端的Android设备,渲染、UI和逻辑代码都是需要研发团队重点关注的,它们的消耗总和占了总开销的80%。与以往不同的是,MMO项目中逻辑代码的耗时占比大幅提升,这主要与角色、怪物的数量越来越多相关。随着其不断增加,逻辑状态的更新开销、AI开销等都在大幅增加,这是需要游戏研发团队中密切关注的耗时瓶颈。

下面我们就来具体分析这些主流模块的开销情况。

二、MMORPG手游CPU模块性能开销分析

1、渲染模块

严重程度:地狱

为了能够更好地反映出各个性能参数的整体使用情况,我们统计了每种性能参数的主体使用范围,其范围区间是[5%~95%],以下数据中P5代表5%,P50代表均值,P95代表95%。

在过去的4个季度中,半透明渲染和不透明渲染在低端设备上的CPU耗时在不断下降,这是非常好的趋势,意味着游戏团队对于引擎渲染模块的理解越来越深入。同时,无论在高、中、低端,Draw Call的数量普遍都保持在较低的范围。

MMORPG手游的Draw Call数量普遍较高,且设备性能越好,数量峰值越高。这主要有以下几方面原因:

  1. 研发团队普遍开始针对不同机型来制定自适应的渲染LOD策略,主要包括模型LOD和Shader LOD等。
  2. 除LOD外,研发团队同样会对一些渲染效果进行有针对性的设置,最常见的是阴影的处理,高端机上开启实时阴影,而低端机上则通过较为简单的阴影面片或Projector来处理。另外,水体模拟也越来越多地在项目中被使用,高端设备上开启水面反射效果,也会增加一定量的Draw Call。
    但就目前数据表明,研发团队已经开始有意地对Draw Call进行控制,UWA建议Draw Call占用的P95 < 200。

随着Android设备整体性能的不断提升,UWA建议目前可将单帧渲染三角形面片数量控制在20万以下。但对于MMO项目来说,可以看到,从2017 Q4开始,Triangle的渲染峰值均值就处于25万以上。这会增加GPU端的渲染压力,需要研发团队时刻关注。
对于不同档次机型的面片数量推荐,UWA目前正在研究中,后续我们会将最新的研究成果在UWA性能简报中进行体现。

2、逻辑代码

严重程度:地狱

  1. GC触发频率很高,是造成卡顿的主要原因之一,目前只有23.2%的项目可以将GC的触发频率控制在1000帧/次以上。
  2. 随着MMORPG游戏越来越重度化,GC平均耗时在逐步上升。GC耗时会逐渐成为游戏运行时的主流性能杀手,需要研发团队时刻注意!

我们可以看到,在过去的四个季度中,Instantiate耗时一直在稳步下降,低端设备中趋势非常明显。这说明大家在项目中不断重视对于资源Instantiate/Destory的管理。

如果大家的项目中仍有大量的Instantiate/Destroy调用,那么我们建议您着重查看UWA线上性能报告中资源管理分类的“资源实例化/激活”页面,通过它可以快速掌握到底具体哪些GameObject在不停地被执行实例化操作,从而更为高效地减少不必要的性能开销。

Shader.Parse 操作是比较突出的性能杀手,目前平均每次调用的CPU耗时主要分布在 22.5~56.5ms。同时,PBR材质开始在大量项目中进行使用,这也是该函数耗时在2018 Q2上增加的主要原因。

3、UI模块

严重程度:地狱

目前我们主要统计了NGUI和UGUI的占比以及详细的使用情况,在UWA测评过的项目中,还存在一些其他UI插件比如FairGUI,基于目前数量较少,并未加入统计。

在刚刚过去的4个季度中,NGUI和UGUI的使用占比呈现反转的趋势。NGUI的项目占比从60%降到了40%,而UGUI的项目占比则刚好相反。对于目前新成立的项目中,UGUI基本上成为了游戏中UI解决方案的首选。

下面我们将分别说明NGUI和UGUI的CPU耗时和堆内存占用情况。

UI模块的性能开销依然很高,但相较于全年相比确实有大幅提升。在全年的统计中,超过90%的研发项目在UI端面临较为严重的性能问题,而在今年则已经下降为50%~60%。这主要是有两方面原因:

  1. UGUI的多线程实现大幅降低了主线程中的压力;
  2. 大家对于UI模块的性能优化有了长足的进步。

但需要注意的是,Unity在5.2版本以后开始将UI的部分计算操作移到子线程中进行,当子线程计算压力较大时,主线程则会出现等待子线程UI重建计算完成,其表现则为WaitingForJob、PutGeometryJobFence等,对于这些函数,在本次报告中的UI耗时中,我们并没有将这两项开销统计在内。

受限于C#端实现效率,在同等复杂环境下,NGUI的堆内存分配确实要大幅高于UGUI。这也是UGUI在底层进行网格拼合的优势所在。但对于已经使用NGUI开发的团队,我们推荐阅读这篇《如何大幅优化NGUI的堆内存分配》来大幅降低项目运行时的堆内存分配。

4、动画模块

严重程度:普通

动画模块最近一年以来的性能表现一直较为平稳。虽然MMO项目中的角色、NPC和怪物等数量持续有在增加,但在这些模型多数是通过GPU Skinning的方式来完成,并非动画模块。这种方式对于实现场景中的大量同种怪物非常有效。关于GPU Skinning的实现方式,建议大家阅读这篇文章:《GPUSkinning_加速骨骼动画》。

5、物理模块

严重程度:普通

物理模块的性能普遍较好,且在低端设备上出现了持续下降的趋势。而在高端设备上,物理模块的耗时则在2018 Q2有所上升,需要研发团队关注。

6、粒子模块

严重程度:普通

粒子系统的CPU开销普遍较低,且总体使用数量峰值在2018年后大幅降低。但我们依然建议研发团队尽可能将数量峰值控制在600以下。对此,建议研发团队经常通过以下两方面来检测自己的粒子特效使用情况:

  1. 粒子系统(特别是技能特效)的配置文件是否过量;
  2. 特效中是否含有长久不用的粒子系统。

三、MMORPG手游内存模块开销分析

内存泄露问题存在持续上升趋势,特别是大家项目中Lua的大量使用,使得内存泄露问题更加明显。在UWA优化过的项目中,逻辑代码C#端对于GameObject、Asset的引用已经明确去除,但往往是因为Lua端的引用,导致了整体项目的内存泄露。内存泄露问题对于整个行业来说已经变得相当严重,泄露率已经高达55%,需要研发团队在接下来的研发中密切重视。

总体内存

严重程度:噩梦

总体内存在2018 Q2上升趋势非常明显,这主要是因为大量超重度MMO游戏的出现所致。目前,项目中的主要内存瓶颈依然是资源和Mono堆内存,对此,我们将在接下来的文章中进行详细分析。

总体堆内存

严重程度:地狱

总体堆内存在2018 Q2上升趋势非常明显,这主要是因为大量超重度MMO游戏的出现所致。就目前而言,我们建议研发团队后续密切关注Mono堆内存的分配情况,不断检测和完善堆内存的分配情况。

项目的内存占用很大一部分来自于资源的使用,下面我们将对项目中主流资源的使用情况进行分析。

纹理资源内存

严重程度:地狱

对于纹理资源来说,在过去的4个季度中,其内存占用处于震荡阶段,虽然在2018 Q1中纹理资源的内存占用大幅下降,但在2018 Q2中随着大批量重度MMO游戏的出现,内存占用又回升到了新的高度。经过这一年来优化方案普及,纹理资源的使用问题已经不再是简单的格式问题,大家已经可以非常有意识地使用硬件压缩格式或者Dither算法的RGBA16格式。而目前的主要问题则已经转变成纹理资源的分辨率过大问题和缓存过量问题:

  1. 对于美术人员制作的高分辨率纹理,真机运行时是否能够“物尽其用”?
  2. 对于我们加载到内存中的纹理,是否确实真正被用于渲染了?

对此,UWA在过去的一年中在游戏项目团队中进行了深入的研究,并在深度优化时不断进行尝试。以数据说话,在过去的50款深度优化游戏项目中,平均每款项目不能“物尽其用”的纹理资源占总数量的18%,以下图为例,build_map2009和terrain_map
1001两张纹理的分辨率分别为1024x1024和512x512,但在游戏运行时,真正用到Mipmap 0层纹理进行渲染的像素却只有0%和1%。也就是说,build_map2009纹理在游戏运行过程中,根本没用过1024x1024的第0层来进行渲染,而terrain_map1001用到原始分辨率的只有1%的像素。对于这种纹理的优化,其实可以将其长宽各降一倍,不仅视觉效果上不会受到影响,但内存却可以降低为原来的四分之一,其加载效率也会更加快速。

同时,加载到内存却长时间没有渲染的纹理更是占到了40%。以下图为例,蓝色线条为项目运行时内存中的纹理数量,而紫色线条则为用于真正渲染的纹理数量,表格则为精确统计的渲染利用率为0的具体资源信息。可以看到,两者存在很大的差距。

上图来自于一款真实的MMO项目,也是目前绝大多数项目纹理使用率的真实情况。也就是说,现在的每款游戏项目中,纹理使用方面都存在大量的内存浪费。因此,UWA建议研发团队对项目中纹理的缓存使用进行特别关注,特别是技能特效的纹理使用。

在我们优化过的大量项目中,很多情况都是技能特效的无效缓存所致,即美术人员做过一批特效用于展示项目的前期效果,而随后团队很可能会以外包的方式来加入第二批或者第三批特效资源,这时大多数的美术人员会将新特效与旧特效混在一起,并Deactive第一批旧特效(因为要考虑以后可能又要重新使用老特效)。久而久之,这些新旧的特效就慢慢积淀下来,然后一并打包到AssetBundle或者最终的发布包中,从而导致了大量资源的无效使用。这种是我们遇到过的常见情况,如果您的项目中也是采用这种开发方式,那么建议大家仔细地排查。

网格资源内存

严重程度:地狱

  1. 网格资源内存峰值主要分布为12.7~ 96.1 MB,且主要集中在40MB以内。
  2. MMORPG游戏的场景普遍较大、角色普遍较多,因此,其网格资源量明显高于其他类型游戏。但从使用趋势上来看,其最近一年的使用趋势较为平稳,均值均在30MB上下浮动。

对于网格资源,在过去的4个季度中,其内存同样大幅提升,这主要是因为现在的MMO已经陆续开始向超大场景进军,8K分辨率已经不再是吃鸡游戏的地形特色了,MMO甚至更大。与纹理资源一样,网格资源也存在着渲染利用率的问题,也同样是大量缓存导致,在此不再赘述。
纹理资源不同的是,网格资源还需要关注另外一项指标,即“渲染密度”。我们将其定义为,每单位数量的像素所能渲染的顶点数量。当渲染密度越大时,其造成的渲染计算浪费概率也就越大,而在游戏运行过程中,这种情况是普遍存在的。下表为一款游戏在运行时渲染密度过大的具体网格资源信息。

以rock_map2003_huoshan为例,其模型顶点数不多,为696个,但其平均每帧能渲染到的像素数则更少,为48个像素。这也说明,平均每个像素渲染14.5个顶点,这其实是无意义的,因为人眼根本就无法分辨。所以通过渲染密度,我们可以更为科学地了解游戏在真机上运行时,哪些资源实际上是被浪费的,从而可以更为准确和高效地对场景进行调整和完善。

动画资源内存

严重程度:普通

动画模块的内存使用趋势较为平稳,平均峰值内存长期控制在20~25MB区间之内。

Shader资源内存

严重程度:普通

Shader内存占用的下降趋势较为明显,特别是在低端设备上。这说明在近一年来,大家对于Shader使用的理解已经越来越清晰。但UWA需要提醒的是,Standard Shader仍然在大家的项目中被经常误引入进来,建议大家在UWA性能简报中的“具体资源使用信息”中特别关注Standard Shader的使用情况。

RenderTexture资源内存

严重程度:噩梦

RenderTexture的内存占用在近一年中下降趋势明显,特别是在低端设备上,持续保持着内存下降趋势。但对于高端设备中,随着大家对于图像后处理效果的需求提升,后续很可能会出现RenderTexture使用程度大幅提升的情况,因此,建议研发团队对RenderTexture密切关注。

粒子系统资源内存

严重程度:噩梦

粒子系统的使用数量过大,从而导致其内存占用过高。对此,其最有效的优化方法还是降低粒子系统的使用数量,目前仍然建议将其数量控制在600个以下。建议研发团队后续对粒子系统的数量(特别是特效中的缓存)密切关注。

四、MMORPG手游资源管理分析

AssetBundle加载方式(Load和LoadAsync)的使用占比已经从去年的69%进一步增涨到今年的84%。毫无疑问,AssetBundle加载方式目前绝大多数研发团队的资源加载首选。

LoadFromFile加载方式一家独大,其使用占比从去年的60%增涨到今年的74%。LoadFromFile+LZ4的组合在移动游戏中加载性能优势明显,已经逐步成为了移动游戏资源加载的不二选择。

  1. 对于Instantiate/Destroy的完善,研发团队时刻关注缓存池的使用是否合理;
  2. 对于Active/Deactive的完善,则需要研发团队尽可能注意避免UI和动画角色的频繁调用,从而尽可能避免不必要的调用开销。

五、UWA 对于MMORPG手游研发团队的建议

  1. 警惕渲染模块和UI模块这两大性能杀手!随着精品化MMORPG项目的日益增多,这两项在接下来依然是研发团队在性能优化时的重中之重!

    • 渲染方面,DrawCall目前在大多数项目中已经不再是性能问题的导火索,但渲染Triangle数量已经俨然成为了渲染模块新的性能瓶颈,大量的草体、花海、麦浪等等,虽然有GPU Instancing的加持,但依然给中低端设备带来了相当大的性能压力,是大家后续游戏研发时的重要关注对象;
    • UI方面,如果说去年的MMORPG手游是处于“端游手游化”的初期阶段,那么今年就是“端游手游化”的成长期阶段。市面上已经出现了几款超级重度的MMO手游,后续则会越来越多。UI网格重建开销在未来相当长的一段时间内仍然是研发团队头痛的问题,在使用UGUI的项目团队中,切记要密切关注WaitForJobGroup和PutGeometryJobFence的性能开销。
  2. 逻辑代码方面,过去一年中研发团队已经加强了对资源管理的监控,所以无论是资源加载还是实例化开销都在持续下降。这是一个非常好的趋势;但游戏项目的自身逻辑开销开始逐步增大,这是因为人物和怪物的数量大幅增加所致,其状态更新更加频繁,AI计算更为重度,建议研发团队后续对此进行密切关注。

  3. 内存泄露问题在今年的项目研发中会非常严重,其持续升高趋势明显,项目占比已经高达55%,研发团队对其必须引起高度重视,内存泄露问题的控制仍然刻不容缓;UWA线上测评报告或者UWA GOT中的内存泄露分析功能可以快速检测和定位堆内存的具体泄露问题和出处,建议研发团队多用、善用。

  4. 在内存优化方面, Mono堆内存、纹理、网格、RenderTexture、粒子系统是大家接下来需要关注的重点,具体的关注点请直接查看之前的相关部分;

  5. 资源加载方面, LoadFromFile(Async)已经是移动游戏项目中的主流加载方式,AssetBundle.Load(Async)同样也是资源加载的主流方式。对于其在Unity 2017和Unity 2018新版本中的加载性能,研发团队可在UWA相关Blog中找到对应的性能比较和分析;

本文来自:https://blog.uwa4d.com/archives/UWABlueBook2018.html