UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 - 博观约取
《镇魂街：天生为王》— 这条街，由UWA共同守护
2022年底，由喀什奥术研发、中手游与奥飞游戏联合发行的3D ARPG手游《镇魂街：天生为王》正式在全平台上线，上线首日全渠道新增即突破200万，成为2022年岁末最值得关注的一款手游新品。 很荣幸UWA参与了该作深度优化的全过程，见证了《镇魂街：天生为王》一步步走来的历程。尽管距离小编上次观看《镇魂街》已有段时间，但当我第一次接触到的时候，还是为制作组的用心所打动了。即便是在已经提前测试过的前提下，依旧在游戏上线首日，迫不及待地再次进入其中。 一方面，作为一名《镇魂街》的IP原著党，小编很满意游戏的画面和音效，游玩过程中仿佛慢慢被拉回了那个守候在屏幕前等待新一集更新的夏天，那位“快递小哥”还是那样热血，一点没变的感觉真好。而另一方面，作为一名重度ACT玩家，爽快的打击感、流畅的指尖操作都在《镇魂街：天生为王》中得到了满足。 当UWA开始为《镇魂街：天生为王》提供深度优化服务后，小编便对其充满了期待，毕竟《镇魂街》是我高中时期最喜欢的动漫，现在终于要以另一种方式再次见面了；在了解了更多项目背后的故事之后，小编打心眼儿里为这群用心还原《镇魂街》的成员们感到敬佩，因为他们真的是保留了印象里的那条《镇魂街》。 秉持着持续为粉丝创造精品内容和互动体验的信念，UWA同《镇魂街：天生为王》的开发团队共同携手，通力合作，努力给玩家呈现更优秀的性能表现。下面我们将从性能数据的角度，呈现《镇魂街：天生为王》的优化历程。 首先来看物理模块耗时对比，从下方物理耗时的前后对比图我们可以发现，优化前的物理模块经常存在3ms左右的耗时，优化后的物理模块主要耗时已经移除。当项目中没有使用物理模拟却依旧存在物理耗时的情况，需要检查是否可以关闭AutoSimulation，从而减少不必要的CPU耗时当项。 再来查看UI耗时曲线，可以发现在优化前的战斗场景中UI耗时经常持续在2-3ms之间、优化后的战斗场景耗时基本维持在1-2ms，UI作为游戏场景的常驻模块，其耗时的降低会提升FPS，从而带来更好的游戏表现。 而针对部分性能开销偏大的场景以及特效，UWA对其进行了GPU耗时分析，以便降低耗时提高游戏运行的流畅度。下图是游戏抽卡页面的GPU耗时对比，经过优化后，均有较大幅度降低，GPU耗时从近50ms降低至25ms左右，性能提升了近一倍。降低GPU所需耗时，能够减轻GPU的压力，我们将更多“好钢”花在“刀刃”上，从而进一步降低手机发热引起的降频、高耗电等情况。 优化前 测试机型：OPPO R17 画质：极致 帧率：16 耗时Top20的DrawCall的GPU耗时为45.49ms。这一帧总共94个DrawCall，GPU耗时为49.52ms。 优化后 测试机型：OPPO R17 画质：极致 帧率：34 耗时Top20的DrawCall的GPU耗时为22.89ms。这一帧总共67个DrawCall，GPU耗时为24.25ms。 而下图则是优化中压力较大的技能，查看优化前后的耗时对比，可以看到在优化前的GPU耗时高达176.94ms，优化后大幅降低至13.79ms，性能提升了近10倍。 优化前 测试机型：OPPO R17 画质：极致 帧率：5 这个技能总共14个DrawCall，GPU耗时为176.94ms。 优化后 测试机型：OPPO R17 画质：极致 这个技能总共9个DrawCall，GPU耗时为13.79ms。 除了深度优化之外，项目组也会定期使用UWA GOT Online、本地资源检测等服务，不仅随时帮助了解项目进度的性能变化，同时也可以与前序工作形成对比，帮助项目的稳定推进。 项目帧率和内存变化趋势 如今，在IP漫改市场热潮渐退的情况下，《镇魂街：天生为王》凭借独特的战斗模式和对《镇魂街》IP的深度理解，依旧逆流而上。相较于优化前，部分场景、技能特效出现的掉帧卡顿等较为明显能够影响游戏体验的负面体验，游戏正式上线后已然将这些问题消化殆尽。不仅如此，还在操作手感、画面流畅度等性能方面收获了不少玩家的好评。 《镇魂街》中有这样一句话：乱世将至英雄四起，人各有命上天注定，有人天生为王有人落草为寇。即便国内“版号仍处寒冬”，但依旧挡不住如《镇魂街：天生为王》这类优秀的作品发出炽热的温度，驱散前方的迷雾。UWA愿为性能保驾护航，衷心祝愿《镇魂街：天生为王》能够在未来的道路上取得更好的成绩！
废土、末日、方舟......这些元素的组合会让你想到什么？放心，你身处的既不是核战后的《辐射》地表，也不是蜷缩在《地铁》中的生活。这里是未来的废土世界，欢迎来到《流浪方舟》。 与印象中的废土背景游戏不同，该作给我的第一印象竟然是有些“清新脱俗”，优秀的立绘、丰富的操作角色、听一遍就想跟着哼的背景音乐，都让我对这款游戏产生了极大的兴趣。 随着对游戏的不断深入体验，我仿佛看到了赛场上像素风的小人们在擂台中彼此撞来撞去，赛场下的英雄们聚在酒馆中谈天说地交流着今日的战斗。当然，仅从游戏的实际体验在别人看来说服力不大，但是从性能数据层面的解读或许对我自己来说更具吸引力，也希望让各位玩家从另一个角度了解《流浪方舟》这款游戏。 很荣幸UWA参与了《流浪方舟》的深度优化工作，通过查看UWA对《流浪方舟》优化前后的性能数据对比，可以在FPS子类指标中发现，不同模块的耗时均值出现了不同幅度的下降。其中同步等待耗时均值和物理均值耗时出现了较大的降低，这两项耗时的降低直接影响到的是项目整体卡顿率的下降从而提升FPS的均值，而这也将会是本篇主要向大家展示的两项优化数据。 由于《流浪方舟》的主要玩法是在擂台上不断与对手进行碰撞，所以物理模块成为了本作优化中比较重要的方面。查看CPU耗时均值可以发现，优化前的物理模块耗时在总体耗时中占比最高，均值达到了15.02ms，峰值最高甚至能够超过500ms以上。 通过查看UWA对《流浪方舟》物理模块的性能优化前后对比的数据，可以发现Physics.FetchResults、Physics.ProcessReports、Physics.Simulate、Physics.Processing等函数的CPU耗时均值在优化后都出现了不同幅度的降低，进一步证明了物理模块的优化是显著的。 物理模块耗时的显著降低，呈现在CPU整体耗时中的降低很明显，查看优化后的耗时均值可以发现物理模块耗时占比已经不再“高居首位”，均值已经降低至7.12ms，且几乎未出现异常峰值的情况。 通过查看同步等待耗时WaitForPresent函数，UWA发现该函数存在持续性的高耗时，证明GPU存在着较大压力。针对《流浪方舟》的GPU深度优化，UWA向研发团队提供了更快速准确定位的优化方向，从而有效降低GPU的耗时开销。 在游戏主界面中，GPU的耗时为19.1ms。通过UWA排查发现是使用了Cycles为36-197的Shader进行渲染，该Shader中包含了非常多没有真正产生渲染效果的Feature的计算，因此复杂度非常高。换句话说就是使用了复杂的Shader来绘制较为“简单”的效果，如下图中绘制边框的DrawCall。UWA推荐使用了复杂度仅为7.0的Shader进行绘制，渲染效果是一致的但是GPU开销极大的下降，由原来的4ms下降为0.2ms。 在主线战斗场景界面，UWA发现了一个耗时非常高，但画面效果几乎不明显的DrawCall，或者仅在特殊时间节点才显示，但是却一直在渲染。在优化后，此效果被移除，这个DrawCall耗时13.4ms，如下图所示。 UWA通过排查还发现，有非常多的UI界面出现了UI叠层的问题，如阵容选择页面中除了可见的内容外，GPU依旧在渲染不可见的主界面的内容，而主界面此时是被完全遮挡、不会被玩家所看见的，这也造成了高达21ms的耗时。优化后，GPU只渲染阵容选择界面的内容，耗时降低至6.25ms。 此外，UWA还对一些特效进行了耗时分析，力求大幅度降低各种技能的耗时。例如此技能优化前GPU耗时是18.2ms，优化后GPU耗时可直接降低到2.1ms。我们通过对于Shader的优化，在尽可能保障视觉效果的同时，大幅降低了GPU Cycles的占用，从而达到该特效GPU大幅优化的效果。 最后通过对比查看《流浪方舟》优化前后的整体GPU模块能够发现，在耗时均值、使用率均值、频率均值等方面都出现了明显改善。 处快节奏的生活中，难得一见如《流浪方舟》般能够放松下身心去游玩的休闲游戏，而作为一款同时拥有PVP、PVE等多种模式爽快战斗的手游，优秀的性能势必会让战斗过程更为流畅，也能够成为游戏的加分项。笔者作为一名参与该作的测试，很希望能够看到越来越多的游戏在UWA服务的支持下性能表现得更为出色，获得更多玩家在游戏体验上的认可。同时作为一名热爱优质游戏的玩家，衷心希望《流浪方舟》能够潜心经营，争取在未来能够用实力征服更多人加入这场流浪的冒险之旅！
2019年8月，天魂网络的一款名为《巨龙城堡》的手游横空出世。作为“魂之刃”系列的第一款产品，同时也是市面上少有的魂系动作游戏，其一经推出便收获大量玩家的关注。有了“一代魂之刃”的经验积累，《魂之刃2》项目很快就在众多玩家的呼声中正式确立。而随着前几日魂之刃系列的续作《代号：魂之刃2》在各大游戏平台上的限量删档测试结束，当各位玩家回味这次测试之时，UWA也想借此机会从性能表现的角度聊聊这款备受关注的游戏。 虽说魂系游戏的玩家数量偏少，但该类型玩家群体的游戏忠实度却是最高的。因此，如何在移动设备上更为流畅地运行动作类游戏，同时又能保留游戏最核心的硬核玩法，成为了《代号：魂之刃2》当下所需要面对的主要问题。在上线测试后不久，收到了大量新老玩家的反馈，有批评也有赞扬，研发团队在这其中认真汲取各种建设性意见，并在每次的测试中进行不同的改进，以达到更适合玩家游玩体验的水平。 很有幸这次UWA能与天魂网络合作，为这款游戏提供了UWA深度优化服务，希望本文能够从测试工程师这个参与者的角度，来描述这款游戏的优化历程，向玩家朋友们展示这款游戏的不断进步。 通过UWA对《代号：魂之刃2》的两次相同机型、间隔一段时间的测试数据来看，其在两次测试间进行了较大优化，最直观的感受就是FPS和卡顿的趋好。下图中的Jank均值可以理解为平均每分钟内的卡顿次数，可以发现优化前的Jank每分钟高达63.46次，与优化后的每分钟13.53次相比，提升巨大，这也意味着玩家在实际体验中对卡顿的感觉会大幅减少，能够拥有更好的游戏体验。 从上图中也能明显发现大于40ms帧数的占比也有明显下降，该指数说明的是在游戏运行过程中，CPU耗时大于40ms的帧数占总帧数的百分比，占比越低则游戏运行更流畅。虽然FPS均值在数值上的提升不是那么明显，但是在总体帧率的运行中还是能够发现，优化后的较低帧数的场景大多数为非战斗场景，对游戏主要战斗场景不会产生明显影响。 通过对比优化前后的总体测试帧率可以发现，优化前的游戏帧率波动幅度大、全程较难稳定在30帧；优化后的帧率波动大幅度减小、能够较长时间稳定在43帧左右，帧数和卡顿的优化无疑是《代号：魂之刃2》的巨大提升。而从玩家在游戏社区内的评论反馈来看，优化提升的效果是明显的，很多玩家都对优化后的结果表示肯定。 除了直观感受层面的体验提升，在更多细节层面，项目组也花了不少心思去优化，以达到更优的结果。对比优化前后的CPU耗时均值可以发现，逻辑代码、渲染耗时都有一定程度的优化。通过UWA的测评结果来看，逻辑代码耗时均值的降低是CPU总体耗时降低的主要原因，直观的表现就是游戏运行更流畅了。 此外通过查看渲染模块的耗时，可以发现该项耗时降低主要是WaitForPresent.CPU的耗时均值从7.27ms大幅降低至1.47ms（该函数是开启了多线程渲染之后的CPU等待GPU的耗时统计）。GPU耗时过高可能会引起卡顿、发热等直观层面的诸多问题，当此函数均值较低时，通常说明GPU的渲染压力较小。 转到GPU模块查看相关性能可以发现，GPU耗时均值从18.82ms降低到12.41ms，进一步证明GPU的压力变小，说明项目组努力优化的方向正确，并具有一定的成效。 关于GPU的优化，UWA给出的建议主要是针对场景渲染面、特效Shader复杂度以及Overdraw等方面。从优化效果看，在对画质影响不明显的情况下，部分画面的Triangle可以从100W面降低到50W面。 在Shader复杂度方面，UWA通过深度优化来分析高GPU压力Shader的相关代码指令，根据不同Keyword对于GPU压力以及画面效果的影响，帮助团队更好地权衡性能与表现。UWA经过两周与项目组的深入沟通和尝试后，游戏中大部分特效可以在效果几乎无损的情况下降低其在移动设备上的GPU性能压力，即大幅降低了同等视觉效果下的GPU ALU和带宽压力，从而达到GPU压力和设备发热大幅降低的效果。 此外，对比优化前后的GC调用频率可以发现，优化后的GC次数大幅度降低，这也表示GC触发得越少，反映在直观感受上即运行时的卡顿次数越少。 敢于静下心来深耕魂系游戏的开发，在这个快节奏的互联网时代属实是一件难得可贵的事情。研发团队的积极优化与运营团队的及时响应，代表了《代号：魂之刃2》团队对游戏的严谨态度，同时这也是团队凝聚力的一种表现。在这“版号寒冬”的大环境中，加之来自市场其他游戏的影响，经历过多轮测试但依旧没有正式上线，这一举动遭到不少玩家的不解。但是团队依旧顶住了所有压力，细心、耐心打磨游戏的每一处细节，只为了正式上线时能够交出一份更好的答卷，做出更精品、对得起玩家期待的游戏。 或许在一些重度主机游戏玩家看来，这款游戏还没能达到他们的高标准高要求。但在小编看来，研发团队正在用他们的热情和真心去浇灌他们所热爱的一切。真心希望《代号：魂之刃2》团队能够继续坚持自己最初的梦想，在这场属于勇者的游戏中取得最终的胜利，早日将优质稳定的游戏呈现给玩家！
今天我们为大家带来由福州朱雀网络研发的MOBA手游《小米超神》的UWA测评报告分析。该游戏在不同配置的移动终端设备上，无论是画面表现力，还是性能开销都非常优异。在此，我们将对该款游戏的性能数据进行深度剖析，希望通过这篇文章可以让大家对移动游戏各个模块的运行效率有更为深刻的认知，并对大家的项目研发有所帮助。 一、CPU性能 该游戏在CPU占用方面的性能非常不错，下图为该游戏在红米Note2设备上进行一场5V5战斗时的性能数据。 可以看出，在红米Note2上运行的19876帧中，超过33ms的帧数占比为13.9%，超过50ms的帧数占比为1.7%，并且从图中可以看出，其CPU耗时较高处主要集中在5V5场景的资源加载阶段。因此，该游戏在战斗时的性能可以说是非常优秀，绝大多数时刻游戏运行非常流畅。 同时，通过进一步统计，该游戏的CPU性能超过了64%的同设备（红米Note2）上测试的其他游戏，其能耗更是低于86%的同设备测试游戏。由于目前国内的MOBA游戏较少，所以上述排名并不是在MOBA类型中的排名，而是在所有类型游戏中的排名。对于一款超重度的MOBA移动游戏来说，该CPU性能和能耗排名可以说是相当出色。 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。下面，我们就详细讲解其CPU性能方面的亮点之处。 1、渲染模块 通过UWA性能测评报告，我们可以看到该游戏详尽的渲染模块性能开销。该游戏在红米Note2设备上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为1.7 ms，主要集中在0.8~3.0 ms范围内（5%~95%）。不透明物体渲染的CPU消耗均值为1.0 ms，主要集中在0.2~1.7 ms范围内（5%~95%）。可以看出，在整个5V5战斗过程中，无论是移动、Farm、Gank还是团战，甚至上高地时，其渲染耗时都稳定在一个较低的耗时区间。这得益于研发团队对于场景模型、蒙皮网格和UI的控制十分得当。 Draw Call峰值为167，且主要集中在 45~130范围内（5%~95%），渲染三角形面片单帧峰值为64900，以上数值均处于合理范围之内。 2、UI模块 该游戏在红米Note2设备上运行时的UI模块CPU开销如下图所示。该游戏使用UGUI作为UI界面的解决方案。经过统计，UI模块总体的CPU占用均值为1.5 ms，主要集中在0.1~3.5 ms（5%~95%），属于合理范围之内。堆内存累积分配为16000帧 2.4MB，平均每帧分配堆内存155.4B，这说明该游戏UI界面的制作及UI重建的影响范围非常合理。目前，UWA推荐UGUI模块中，平均每帧堆内存分配尽可能控制在200B以下。 战斗场景中，UI系统的性能耗时主要是由UI元素的状态变化而导致的，比如血条、飘字等HUD的移动、消隐等。这种操作稍不注意，就会带来较高的UI网格重建开销。所以，UI界面的研发看似直观、简单，但是其对于制作时的层层考究和运行时的耐心调优，则是一款产品是否“匠心”的试金石。以下则为《小米超神》这款产品在经过几轮优化后的UI性能对比图。 3、动画模块 在UWA测评报告中，该游戏运行时的动画模块CPU开销如下图所示。可以看出，除进入场景时出现CPU高值外，其在战斗副本中的CPU开销均控制在较低水平。Animator.Update的CPU均值为2.0 ms，主要集中在0.1~4.3ms区间内，对于MOBA项目5V5场景来说，基本上每帧均有90-130个物体在进行运动（除英雄、小兵之外，还有信使宠物、野怪、塔、插眼等等），由于玩家可以随意查看地图上任何一个角落的特点，其每帧的动画系统压力要比常规的MMO游戏大上数倍。因此，《小米超神》可以将其控制在均值2.0ms的水平线上，已经是非常优秀的数据了。 同时，经过进一步检测发现，动画模块的耗时主要由Animators.ProcessAnimationsJob和Animators.FireAnimationEventsAndBehaviours导致，前者主要是持续的累积耗时，而后者则是非连续的“尖刺”开销。前者是动画系统对于AnimationClip的读取和计算耗时所致，其耗时大小与当前帧参与计算的骨骼节点数、动画曲线数、动画执行状态和Animator Controller的具体设置相关，其具体说明可参见《Unity中动画系统性能优化方案回顾》；后者则是动画事件的具体耗时，主要是项目逻辑代码的性能开销，此处研发团队可以通过性能堆栈来进一步查看其逻辑代码的开销是否有进一步的优化空间。 4、GC 调用 该研发团队对于GC调用频率控制得非常出众，游戏在运行过程中，GC调用频率为1656帧/次，优于目前93%的行业内游戏。一般来说，我们建议一款项目的GC调用频率可以控制在1000帧/次以上。 该游戏的GC调用频率如此优秀，主要得益于研发团队对于项目代码堆内存的控制。下图为游戏运行20000帧的代码堆内存具体分配情况，其Top10函数的堆内存分配总和不超过80MB，足见该团队对于堆内存分配的理解非常深刻。 当前版本的堆内存分配仍然有进一步下降的空间，从堆栈信息中可以看到，其Log输出仍然存在一定堆内存分配，建议研发团队在Release版本中将非关键性Log进行屏蔽。 二、内存模块 《小米超神》在内存上的表现如下图所示。总内存峰值达到297MB，Mono堆内存峰值为48.9MB。297MB的总内存分配相对来说略高，研发团队可尝试在低内存机器上对资源进行进一步控制，从而降低低内存机器上的内存占用。 1、Mono堆内存 从下图可知，该游戏的总体Mono堆内存控制得很好，在20000帧中，Mono的堆内存峰值为48.9MB，该值略高（UWA建议<40MB）。从图中看，是战斗最后上高地时突然出现了较高的堆内存分配，迫使Mono堆内存上涨了8MB（如下图红框所示），对此，研发团队可以根据具体位置查看其堆内存分配，即可定位其具体的堆内存分配根源。 但是，从走势上来看，其Used Mono堆内存占用在5V5战斗结束后，并未完全回落到场景之前（如蓝框所示），这一点需要引起研发团队注意，确认其是否为部分指定容器缓存所致，从而排查项目是否存在堆内存泄露的隐患。 2、资源内存 经过统计，该游戏运行时的纹理资源数量峰值为1003个，内存占用峰值54.8MB。研发团队将纹理内存占用控制得很低，目前仅高于30%的行业项目。经过统计，在内存占用峰值处，ETC1和ETC2格式纹理占有835个，RGBA32格式纹理共占有89个，RGB24格式纹理占有5个，其余为RGBA16格式纹理。 纹理资源在项目运行期间的总体使用情况： 对于纹理资源的优化，一般可分为以下几种： （1）使用更合适的纹理格式 从上图中可以看到，在整个游戏一场5V5战斗过程中，RGBA32格式纹理的使用数量较多，其使用总量已经超过了91%的的行业项目。对此，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理（Android平台）进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。而对于无法进行硬件压缩的纹理，可以通过Dither方法尝试将其转换成RGBA16格式的纹理，具体做法可以参考Unity图片优化神器 - Dither算法进阶方案。 （2）使用更精准的纹理分辨率 一般来说，为了让模型看上去更加精美，除Mesh模型本身以外，其对应的纹理都会选用较高的纹理尺寸，从而让其看上去更加精致。但是，由于渲染物体在真正的游戏中相对于相机是有远近之分的，其显卡底层往往没有（或根本不需要）使用如此高的分辨率来进行渲染，从而就造成了大量的资源浪费，这在我们深度优化过的项目中比比皆是。因此，我们建议可以通过UWA线上测评报告中GPU性能的Mipmap功能页面来直接查看游戏运行时，其底层的纹理分辨率使用情况，如下图所示。 同时，在深度优化报告中，我们也会进行更大量的测试和几十亿像素累积分析，从而来精准指出到底哪些纹理资源的分辨率制作过高，可在不影响视觉效果的前提下，将其分辨率缩小4倍、16倍甚至更多。《小米超神》项目通过这种方式不断优化，其5V5场景的纹理内存已经从之前的78MB降到了现在的52MB。 以上是纹理资源的使用情况，其他资源的内存占用情况如下： 网格资源在项目运行期间的总体使用情况： Mesh资源的内存占用较高，高于60%的行业项目。对于Mesh资源内存的优化，主要有以下几种方法： （1）控制网格顶点属性的使用 详细检测网格模型中的Color数据和Tangent数据，当不需要时切记要将其进行去除，否则会在场景模型拼合时产生大量的内存浪费，具体详细说明可以参考《移动游戏加载性能和内存管理全解析》。 （2）控制网格顶点的数量 详细检测网格模型的顶点数(或面片数）使用是否过大。这是一个说起来容易但实施起来很难的问题，其难点在于如何定义一个Mesh网格的顶点数是否过大。在UWA测评报告中会有一个建议，即建议将Mesh网格顶点数控制在1500个以下。但实际上，这其实是一个“不科学”的规定，因为没有任何一个理论可以证明，其网格数量大于1500就是不合格，或则小于1500就一定合格。所以，我们这一年来花了大量的时间来寻求一种更为合理、科学的判断规则。我们认为判断一个网格模型使用是否合规并不应该是“静态”检测，而应该是一种“动态”检测，与上述纹理资源的检测一样，我们应该去看网格资源在底层渲染时到底占据了多少像素，从而以一种密度统计的方式来判断其网格使用量是否合理。因此，我们提出了一种网格模型测量标准，即“网格模型渲染密度”，其表示每单位数量（比如，1万）像素中，其网格模型的渲染顶点数量。 下图则为游戏运行过程中的网格模型渲染密度统计值。可以看出，虽然第一个模型“Mod_xyc_fz1001”的顶点数仅为1168，但其在游戏运行时平均每帧的渲染像素量仅为34.91个，也就是说平均每个像素要渲染33个网格顶点，这显然是一种浪费。因此，通过“渲染密度”这一检测方式，可以反映任何一个模型在游戏运行时的使用情况。在我们来看，这是一个比单纯设定1500更加合理的判断规则。 AnimationClip资源在项目运行期间的总体使用情况： AnimationClip的内存占用较高，高于76%的全类型游戏项目。对于一款MOBA项目来说，其内存占用较高是可以理解的，因为其战斗副本中拥有大量的动画模型，比如英雄、小兵、野怪、塔、基地等建筑等等。对此，仅能建议研发团队尝试从数量上进行进一步地缩减，以降低其内存的使用。同时，对于动画片段内存的一般优化还有“缩减精度”、“使用Humanoid类型”等方法，其具体优化方法可以参考《Unity中动画系统性能优化方案回顾》。 三、资源管理 该游戏在资源实例化/销毁、Active/Deactive等方面做的非常出色！在游戏运行的20000帧中，Instantiate和Destroy调用次数分别为1653次和4019次，而Active和Deactive调用次数则分别为116次和1447次。同时，对于Instantiate和Destroy操作来说，其主要调用均在进出战斗场景处，副本中虽有Instantiate调用，但无论是频率还是CPU耗时，均处于合理范围之内，如下图所示。 对于GameObject相关的资源管理，我们的建议如下： （1）对项目中存在频繁Instantiate/Destroy操作的GameObject一定要进行大力彻查，下图即为某一项目的Instantiate实例化详情，我们建议对于红框处高频率和耗时的操作重点排查，因为其无论是CPU还是堆内存都对项目性能造成非常大的杀伤力！ （2）频繁的Active/Deactive操作不仅会造成CPU的浪费，同时，它还很可能间接造成更大的CPU耗时，比如Animator.Initialize耗时。在此，我们不妨看下另一款游戏的Animator.Initialize调用情况，如下图所示，其调用的频率和耗时较高，这就是频繁的Active/Deactive操作所造成的结果。因此，对于GameObject不必要的Active和Deactive操作进行控制，是非常有必要的。更为详细的资源加载性能优化总结，可参见《Unity移动游戏加载性能和内存管理全解析》。 （3）不断检测、不断完善，优化是一个需要不断迭代、持之以恒的事情。下图则为《小米超神》经过几轮优化之后的资源管理变化情况。 以上则为《小米超神》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、非常少的堆内存分配以及引擎模块间的合理使用，足以看出该研发团队非常深厚的技术功底和对于引擎相当优秀的把控能力。 最后，非常感谢《小米超神》研发团队对 UWA 的认可和支持。感谢他们乐意将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的MOBA手游在各个模块上应该做到怎样的程度。同时，也希望更多的开发团队可以与我们一起来分享他们的性能数据，让更多的游戏开发者受益！ 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能测评与优化 2）资源检测与分析 3）UWA GOT 三大工具，帮助开发者在短时间内大幅度提升性能表现；同时其搭建的知识分享的博客（blog.uwa4d.com）和答疑解惑的互动平台（answer.uwa4d.com）使广大开发者收益，UWA以实力和态度诠释对性能优化的定义：问题的答案永远“在现场”，解决你的性能问题，才叫“优化”。
今天我们为大家带来由上海非钰数码科技的FPS手游《战地先锋》的 UWA测评报告分析。该游戏在各种档次的移动终端设备上，无论是画面表现力，还是性能开销都非常优异。在此，我们将对该款游戏的性能数据进行深度剖析，希望通过这篇文章可以让大家对移动游戏各个模块的运行效率有更为深刻的认知，并对大家的项目研发有所帮助。 一、CPU性能 该游戏在CPU占用方面的性能非常不错，下图为该游戏在红米Note2 设备上按照剧情进行游戏时的性能数据。可以看出，在红米Note2 上运行的24979帧中，超过33ms的帧数占比为4.3%，超过50ms的帧数占比为1.2%。考虑到切换场景时资源加载的开销，一款游戏如果超过33ms的帧数占比低于10%，则说明该游戏在绝大多数时刻的运行中都是非常流畅的。 通过进一步统计，该游戏的CPU性能超过了84%的红米Note2设备上的测试游戏，其能耗更是低于91%的同设备测试游戏。 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。下面，我们就详细讲解一下其CPU性能方面的亮点之处。 1、渲染模块 通过UWA性能测评报告，我们可以看到该游戏详尽的渲染模块性能开销。该游戏在红米Note2设备上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为1.5 ms，主要集中在 0.7~2.7ms 范围内（5%~95%）。不透明物体渲染的CPU消耗均值为1.8 ms，主要集中在 0.2~4.6ms范围内（5%~95%）。 Draw Call峰值为340，虽然峰值较高，但仅在场景切换处出现，这是因为项目在动态加载后通过代码调用StaticBatching的方式来合并Draw Call，所以可以看到Draw Call数量在进入场景后迅速回落。同时，Draw Call数量主要集中在 48~179 范围内（5%~95%），属于合理范围之内。 下图为该游戏在红米Note2上的具体CPU性能堆栈。可以看到，该游戏在红米Note2上无论是不透明开销还是半透明开销均处于较低水平，这得益于研发团队对于场景模型、蒙皮网格和UI的控制十分得当。 美中不足的是Shader.SetPass稍高，这主要是渲染模块中RenderState的切换较为频繁所致，对此，建议大家对场景中的Material数量进行控制，具体可以参考：《使用MaterialPropertyBlock来替换Material属性操作》 2、UI模块 该游戏在红米Note2设备上运行时的UI模块CPU开销如下图所示。该游戏使用UGUI作为UI界面的解决方案。经过统计，UI模块总体的CPU占用均值为1.9ms，主要集中在0.1~3.6ms范围内（5%~95%），属于合理范围之内。 其均值高于70%的行业数据，这是因为该项目使用的是Unity 4.7版本进行开发，该Unity版本中，UGUI并没有像Unity 5.3版本以后将部分拼合操作放到子线程中进行。在这一点上，Unity 4.x的UGUI性能较之5.3+版本确实要多一些性能上的开销。堆内存平均每帧分配为5.5B，仅高于5%的行业项目，这说明该游戏UI界面的制作及UI重建的影响范围非常合理。目前，UWA推荐UGUI模块中，平均每帧堆内存分配尽可能控制在2KB以下。 从下图中可以看出，Canvas.SendWillRenderCanvases在不同的运行时刻均出现CPU高值，但通过运行截图可以看到，其共同特点是CPU耗时高值均发生在画面底层的UI选人界面出现时。因此，该UI界面的出现或相关操作极有可能是引发Canvas.SendWillRenderCanvases CPU过高的原因，建议研发团队对该界面进行进一步检测。 3、动画模块 在UWA测评报告中，该游戏运行时的动画模块CPU开销如下图所示。 可以看出，除进入场景时出现CPU高值外，其在战斗副本中的CPU开销均控制在较低水平。Animator.Update的CPU均值为1.8ms，主要集中在0.1~3.4ms区间内，其性能较为优秀，高于28%的行业项目。同时，MeshSkinning.Update的CPU均值为1.8ms，主要集中在0.1~3.4ms区间内，高于21%的行业数据。 同时，经过进一步检测发现，其进入副本时的CPU高值均为lhAnimatorEvent.OnEventCallback回调函数所致，具体的CPU耗时堆栈如下图所示。通过此堆栈可知，其耗时主要为UI界面的加载耗时，且进一步通过资源管理信息可知其主要开销为luaUI_PK(Clone)的Active操作和luaUI_Hall(Clone)的Deactive操作所致。因此，建议研发团队可进一步检测该UI的制作是否合理，并对其进行完善。 4、GC调用 该研发团队对于GC调用频率控制得非常出众，游戏在运行过程中，GC调用频率为1921帧/次，优于目前95%的行业内游戏。 一般来说，如果一款项目的GC调用频率可以控制在1000帧/次以上，就已经相当出众了。该游戏的GC调用频率如此优秀，主要得益于研发团队对于项目代码堆内存的控制。下图为游戏运行25000帧的代码堆内存具体分配情况。对于使用UGUI的游戏来说，我们建议游戏运行每1万帧中，Top10函数的堆内存分配总和小于30MB，而该游戏运行25000帧，其Top10函数的堆内存分配总和才26.91MB，足见该团队对于堆内存分配的理解非常深刻。 二、内存模块 《战地先锋》在内存上的表现如下图所示。总内存峰值达到249MB，Mono堆内存峰值为32.5MB。243MB的总内存分配相对来说略高，研发团队可尝试在低端机器上对资源进行进一步控制，从而降低低端机器上的内存占用。 1、Mono堆内存 从上图可知，该游戏的总体Mono堆内存控制得很好，在25000帧中，Mono的堆内存峰值仅为 32.5MB。该值属于合理范围之内（<40MB）。 但是，从走势上来看，其堆内存的占用在游戏运行过程中持续处于上升趋势，对此，建议研发团队对缓存池进行进一步检测，排查项目是否存在堆内存泄露的隐患。 2、资源内存 经过统计，该游戏的纹理资源数量峰值为618个，内存占用峰值119.5MB。纹理内存占用较高，目前高于82%的行业项目。经过统计，在内存占用峰值处，ETC1格式纹理占有221个，Alpha8格式纹理占有5个，RGBA32和ARGB32格式纹理共占有120个，RGB24格式纹理占有87个，其余为RGBA16格式纹理。 对于RGBA32、ARGB32的纹理，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理（Android平台）进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。而对于无法进行硬件压缩的纹理，可以通过Dither方法尝试将其转换成RGBA16格式的纹理，具体做法可以参考此篇文章。 其他资源的内存占用情况如下： Mesh资源： 内存峰值高于41%的项目 AnimationClip资源： 内存峰值高于40%的项目 AudoClip资源： 内存峰值高于73%的项目 AudioClip的内存占用较高，高于73%的行业项目。对此，研发团队可尝试将内存占用较高的音频资源通过Stream的方式来进行加载，该方式可极大降低AudioClip资源的内存占用。 以上则为《战地先锋》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、非常少的堆内存分配以及引擎模块间的合理使用，足以看出该研发团队非常深厚的技术功底和对于引擎相当优秀的把控能力。 三、性能优化、进无止境 该游戏在Shader加载和GameObject Active/Deactive方面仍有一定的提升空间。在此，我们对其进行罗列，希望同样可以帮助到大家的研发项目。 1、Shader加载 目前，游戏副本切换时存在较高的Shader解析（Shader.Parse)开销，如下图所示。通过具体资源信息中的Shader资源分析，可以定位是如下几个Shader的加载耗时，对此，建议研发团队尝试对频繁使用的Shader进行预加载并常驻内存，从而减少不必要的Shader重复加载耗时。 2、GameObject Active/Deactive调用次数过高 该游戏在运行过程中，GameObject Active/Deactive的调用次数过高，在游戏运行的25000帧中，Active调用268952次，Deactive调用393490次。其调用的具体次数如下图所示（下图为游戏运行每10帧进行一次Sample，而每个Sample的数值为前10帧中Active/Deactive调用次数的总和。 其中，GameObject的Active/Deactive Top10资源信息具体如下所示，因此，研发团队可通过下表直接对频繁进行Active的GameObject进行完善。Deactive的完善亦然。 频繁的Active/Deactive操作不仅会造成CPU的浪费，同时，它还很可能间接造成更大的CPU耗时，比如Animator.Initialize耗时。该游戏的Animator.Initialize调用较为频繁，且耗时较高，如下图所示，而这就是频繁的Active/Deactive操作所造成的结果。因此，对于GameObject不必要的Active和Deactive操作进行控制，是非常有必要的。 最后，非常感谢《战地先锋》研发团队对 UWA 的认可和支持。感谢他们乐于将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的3D移动游戏在各个模块上可以做到怎样的程度。同时，也欢迎更多的开发团队可以与我们一起来分享你们的性能数据，让更多的游戏开发者受益！ PS：安利这款FPS手游，在TapTap上已经获得了8.6的高分，并将于9月7日在14个安卓渠道同时开启付费删档测试，欢迎大家来预约！ 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 2）资源检测与分析 3）UWA GOT 三大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。
UWA助力独立游戏开发！《江湖X：汉家江湖》性能诊断精讲！
上周，我们对当下一款高自由度的独立武侠游戏《江湖X：汉家江湖》进行了性能诊断。其画风新奇，玩法独特，并获苹果首页推荐。同时，在与该开发团队交流的过程中，UWA也发现了若干独立游戏中可能普遍存在的问题，在此分享给大家，希望也能对大家的项目起到借鉴作用。 感谢该游戏的研发团队—汉家松鼠的分享，希望通过这个游戏的性能精讲，助力更多开发者节省优化的时间，将更多精力集中在游戏的开发和制作中去。 一、快速定位性能瓶颈 我们知道，衡量一款游戏的性能主要参考CPU、内存、GPU等几大指标。而UWA性能检测工具能帮我们从中快速定位性能问题。首先，我们通过查看UWA报告的 优化任务列表 来明确目前的性能瓶颈和接下去的优化方向。 任务列表显示目前的性能问题主要集中在： 1、总体内存占用较大； 2、纹理资源内存占用过高； 3、堆内存占用较大； 4、GC调用频率过高。 由于总体内存包含了资源内存和堆内存，而GC调用频率又和堆内存分配有关，所以我们很容易得出问题主要集中在堆内存和资源内存这部分。下图为该游戏在测试的十分钟内内存的变化趋势。 下面我们就从资源内存和堆内存这两块，分别为大家说明下优化的方法。 二、堆内存占用 1.堆内存占用分析 上图可以看到该项目最大的问题是堆内存，在测试的十多分钟内达到了195MB的峰值，远远超过了UWA的推荐值50MB。堆内存的峰值一方面影响内存的大小、另一方面影响GC的CPU开销，需要大家特别注意。 上图是Mono堆内存的走势图，测试一开始就达到了150MB，这说明很有可能在启动的时候读取了大量的配置文件。我们在图中选中了某一帧，可以看到黄色线条Unused Mono已经达到了60MB，由于Android设备上，Mono堆内存一旦分配就不会返还给系统，这意味着60MB的堆内存已经白白浪费了。一般来说Unused Mono我们建议小于10MB。从这款游戏的体量来看，其Mono堆内存至少可以减去70MB。 关于堆内存的详细分配，我们可以查看Mono堆内存报告。如下图所示，我们看到该游戏在运行了十多分钟后，一共分配了211MB堆内存。点开函数的堆栈信息后发现，211MB的构成为：MapUI（90MB），UITools（74MB），ServerSelectUI（35MB），BattleField（10MB）。 我们来分析下堆内存占用较大的几个函数的开销： 1）点开每一级的函数并进行分析，在53MB的占用下面可以看到有一个堆内存分配很大的实例化操作，这就是Unity的Instantiate，在该项目中主要和Sprite或UI相关。一般来说，实例化次数越多，堆内存越高。 Q：实例化会占用堆内存的开销吗？如果Prefab特别大且复杂，那实例化出来的纹理会占用堆内存吗？ 会的。Unity本身在Instantiate调用的时候就会产生一定的堆内存开销。所以我们不建议频繁地Instantiate和Destroy，因为会产生堆内存碎片。同时，实例化操作也会导致其挂载的脚本进行初始化操作，比如..ctor操作, Awake操作等等。 在此，我们建议可以通过UWA报告的“资源实例化/激活”模块来查看具体的实例化内容，下图中Instantiate Gameobject数量，有3814次，这个过于频繁，可以考虑缓存来减少实例化的操作。 2）另外一个堆内存比较大的开销是Get Data，看到是反序列化XML文件，在每次反序列化文件的时候都会有一个LoadObjectFromXML的堆内存分配。 以此类推，其他部分大家也可以通过Mono堆内存报告，逐一定位问题。 2.堆内存泄露分析 在UWA的Mono堆内存报告中，我们可以选择两帧数据(第32000帧和第5000帧)进行对比，查看是否存在堆内存泄漏。例如案例中提到：对比后发现有一个Dictionary产生的堆内存一直在涨，增长了2.92MB。我们可以对照堆栈信息中罗列的函数查看哪个Dictionary Size占用的堆内存一直在增长，是否合理，为什么没有销毁，是确实需要缓存还是泄露，从而进行修改即可。 又例如：看到在AddLocation中涨了0.7MB，其中大量的是UI的实例化，我们通过查看变量类型发现这个和UI或Sprite相关，有342个GameObject没有被释放。查看方法是：AddLocation里肯定会调用实例化，实例化出来的1700多个变量究竟放在了哪里，是另外一个池子，还是Lua里，为什么没有被卸载。 堆内存分析模块总结：大量的实例化操作和配置文件读取造成了较高的堆内存分配，可以通过UWA报告的Mono堆内存模块来进行逐一优化。 三、资源内存 资源部分包括纹理、Shader、网格、粒子系统、动画片段、音频等。该项目的资源问题主要集中在冗余以及格式的处理上。需要大家注意的是：虽然部分冗余的资源可能对内存不会造成可观的影响，但是资源的数量会直接影响加载速度。 下面我们就以这款游戏的纹理资源为例来为大家说明，可以看到测试的十多分钟内，纹理资源高达87MB，对于纹理资源的内存占用，我们建议尽可能控制在50MB以下。造成的原因很可能是 1）纹理冗余 2）纹理格式。 1.疑似冗余 在纹理资源的具体使用列表中，我们看到大量资源的数量峰值为2和3，即表示可能存在了冗余，其中有个名为“SpriteAtlasTexture-ui”的资源很可能在游戏包中存在两份，即造成了8MB的冗余。在此我们建议研发团队使用线上的资源检测与分析，通过几分钟就能确定AssetBundle中存在多少冗余的资源，通过改善资源的依赖关系和打包方式，将这部分冗余降为0。 很多朋友可能疑问，是否能够真正做到零冗余，在此我们建议大家可以参考我们之前的推文：Unity 零冗余解决方案。 2.纹理格式 同时，我们也在上述资源中看到有不少较高分辨率如2048*2048、格式为RGBA16的纹理，根据名字我们推测是人物的胡子、嘴巴、鼻子等，这些我们建议美术效果允许的情况下尽可能换成硬件支持的压缩格式。 Q：一般来说，资源部分建议iOS和Android分开打包吗？ 是的，我们建议这么做。本身iOS和Android的硬件压缩格式都是不一样的，我们建议iOS上尽量用PVRTC，Android上尽量用ETC。两者都是有损压缩，可能存在色阶问题，但目前来说的确没有完美的解决方案，只能尽量避免。但值得大家注意的是，如果在Android上你觉得RGBA16和ETC的效果差不多，一定要尽量用ETC格式，这样既能减少内存又能提升加载效率。大家可以参考我们之前的技术推文《加载模块深度解析之纹理篇》来加深理解。 四、CPU性能 除此之外，我们再来看看性能其他部分是否有值得完善的地方。 1.渲染模块 由于项目主要用Sprite2D来渲染，场景中几乎没有不透明的东西，所以不透明的耗时比较低，半透明耗时高主要是由于Sprite的渲染所致，大概在10-20ms。具体如何定位呢？我们在CPU时间占用页面选择Camera.Render，这个就是Unity引擎的渲染模块。 我们可以看到渲染模块的具体耗时分布：Drawing 81%（大家看到的不透明和半透明之和，其中半透明72%，不透明6%），Culling是11%，即裁剪，一般在渲染的时候都会有，我们建议控制在10%~20%，如果后续发现Culling高过20%就值得大家注意了。 所以很明显，半透明的开销很高，其中又可分为两部分，BatchRenderer.Add占了32%，BatchRenderer.Flush占了21%。BatchRenderer.Add点开后有个CanvasBatchIntermediateRenderer.RenderSubBatch，这主要是UGUI造成的开销，右边的调用次数608883其实就是UGUI的DrawCall，在1.5w帧的测试中，这相当于每一帧至少有40个Drawcall，是比较高的。 BatchRenderer.Flush点开是SpriteRender.Renderer。这也是我们上文中提到的某些场景中耗时较高的部分。这些是需要大家注意的，建议研发团队降低其渲染Draw Call来进行优化。 总结来看，SpriteRender的开销很高，在10-20ms震荡，建议通过降低Draw Call来进行优化。UI这里的DrawCall，我们建议控制在20-30以内，目前64是比较高的，而且该项目的UI并不复杂，完全可以控制在30以内，这样UI部分的耗时就能降低到3ms以下。 Q：我们人物的脸是图集捏出来的。头像也是由很多图片做成的，导致十多个DrawCall，很多东西都是来自于不同的Atlas，覆盖不同的层级，一个被另一个交叉叠着，来达到修改面部样子和表情的效果。 理论上是应该避免的，但具体的UI优化，我们目前只能通过现场查看UI的制作才能给出具体的方案。一般遵守这样的原则：尽可能把频繁使用的元素放在一起。所以一个方法是检测玩家的数据，大体上用了哪些头发、哪些眉毛等，把高频率的放在一起，但是这么做并不保险。另一个方式是动态拼合，即在运行时对玩家的选择拼合Atlas，这种方法可以让拼合更有针对性，但会有一定的性能开销。 2.UI模块 我们再说下UI方面的耗时，在分析&建议中，我们看到UI的CPU占用主要集中在0~8.9ms，这个比较高，我们建议的范围是0~5ms ，这说明：1）UI做得比较大，Canvas里面很多东西， 2）UI在频繁地重建。 关于UI模块的开销，我们也可以从UWA报告的高CPU函数中看到两个UI相关的函数：PutGeometryJobFence和WaitingForJob，如果大家的测评报告中这两项也很高，那么建议对项目中的UI系统进行大力优化。 以上就是该游戏的性能诊断，我们主要从该项目的UWA性能报告中反映的内存、UI以及渲染等问题出发，通过数据报告的查看对比，整理出了一条较为完整的优化思路，希望能对大家的自身项目有所启发。 后续，UWA也将继续为大家推送更多性能诊断的实战分享，期待大家能从根本上逐渐掌握性能优化的思路，从此优化不再盲目。 关于UWA 由侑虎科技开发的游戏/VR应用性能优化平台，目前提供 1）性能检测与优化 和 2）资源检测与分析 两大工具。同时，我们也会为大家开发更省心的功能，希望通过它们可以减少开发者反复测试定位问题的时间，从而将更多的精力集中在项目开发和解决问题中，能为大家项目研发省下的任何一分一秒，都是UWA团队的骄傲。
《聚爆Implosion》性能精析：这是我们测过性能最棒的手游，没有之一！
今天我们为大家带来由台湾雷亚游戏研发、龙渊网络发行的3DARPG移动游戏《聚爆Implosion》的UWA测评报告分析。从画面表现力上来看，该游戏无疑为一款重度3D ARPG移动游戏，而且，它在各种档次移动设备上的性能效率几乎无可挑剔。可以毫不夸张地说，《聚爆Implosion》是目前UWA测评过的所有游戏中性能最棒的一款！在此，我们将对该款游戏的性能数据进行深度剖析，希望通过这篇文章可以让大家对移动游戏各个模块的运行效率有更为深刻的认知，并对大家的项目研发有所帮助。 官方网址：http://www.implosion.com.cn， 赶紧来体验富有冲击力的人物场景与超快节奏的打斗吧！ CPU性能 该游戏在CPU占用方面的性能非常优异。我们在红米2和华为6Plus两款中低端设备上按照剧情进行测试，下图则为对应的运行性能数据。 红米2： 华为6Plus： 可以看出，在红米2上运行的18143帧中，超过33ms的帧数占比为11.1%，超过50ms的帧数占比为1.3%。在华为6Plus上运行的16026帧中，超过33ms的帧数占比为8.7%，超过50ms的帧数占比为3.3%。目前，在我们测评过的重度ARPG游戏中，能在红米2上达到这样如此高效的运行效率，只此一款！ 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。下面，我们就详细讲解一下其CPU性能方面的亮点之处。 1）渲染模块 通过UWA性能测评报告，我们可以看到该游戏详尽的渲染模块性能开销。该游戏在红米2上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为 1.3 ms，主要集中在 0.0~3.7ms 范围内（5%~95%）。不透明物体渲染的CPU消耗均值为 4.2 ms，主要集中在 0.0~13.9ms范围内（5%~95%）。Draw Call峰值为 142，且主要集中在 4~115 范围内（5%~95%），均属于合理范围之内。 该游戏在华为6Plus上运行时的渲染模块CPU开销如下图所示。可以看出，虽然是中低端机，但较之红米2，其渲染模块的性能开销已经大幅下降。通过统计，半透明物体渲染的CPU消耗均值为 1.0 ms，主要集中在 0.0~1.9ms 范围内（5%~95%）。不透明物体渲染的CPU消耗均值为 2.7 ms，主要集中在 0.0~5.9ms范围内（5%~95%）。Draw Call峰值为 154，且主要集中在 5~120 范围内（5%~95%），均属于合理范围之内。 下图为该游戏在红米2上的具体CPU性能堆栈。可以看到，该游戏在红米2上开启了实时阴影功能，且仅ShadowMap的渲染一项则占据了总渲染开销的7%，考虑到渲染ShadowMap时接收阴影物体的重绘，实时阴影带来的真实开销可能占据10%左右。这也是该游戏在红米2这种低端机上不透明渲染开销较大的主要原因之一。 同时，从性能堆栈中可以看到，该游戏同样开启了图像后处理特效功能，占据总体渲染性能的13%。这是因为图像后处理特效在战斗副本中全程开启。下图为Graphics.Blit在游戏运行时的CPU占用情况。 在低端设备上开启了实时阴影功能和图像后处理，并达到了如此高的渲染效率，这足以说明了研发团队对于移动设备渲染底层的深刻理解和深厚的功底！ 2）动画模块 在UWA测评报告中，该游戏运行时的动画模块CPU开销如下图所示。通过统计，MeshSkinning.Update的CPU占用主要集中在 0.0~1.5ms 区间，该值处于合理范围之内。 另外，游戏中的动画系统主要以Mecanim为主，Animator.Update的CPU占用主要集中在 0.0~4.5ms 区间，其运行时的CPU占用如下图所示。 我们来继续查看一下它的性能堆栈，可以看到，Animator.Update函数的主要CPU占用为两个函数所占据： 1）MOnAnimatorMoveDelegate.OnAnimatorMove，占据该函数总开销的41%； 2）FK & Statemachine，占据该函数总开销的30%。 对于前者，这个是开发团队重写的OnAnimatorMove函数，如果您的项目中也可以看到相似的开销，则需要您去仔细检测一下项目中重写的OnAnimatorMove函数，看看是否有不必要的CPU占用可以优化。对于后者，则是Mecanim动画系统的自身状态机控制开销。一般来说，Animator Controller中的状态机越复杂，该项越高。如果研发团队同样也是该项值较高，我们建议直接查看Animator Controller的制作，并尝试对其进行简化。 注意：我们不推荐将大量甚至所有角色用到的AnimationClip全部放入到Animator Controller中，因为这会带来两个问题： Animator Controller中到处都是状态机的连接线，复杂且不易于维护； Animator Controller初始化时的开销较高。 因此，我们建议研发团队善用AnimatorOverrideController，在Runtime时动态替换所需的AnimationClip，从而尽可能避免上述问题的出现。 3）粒子系统 在UWA测评报告中，该游戏运行时的粒子系统CPU开销如下图所示。可以看出，ParticleSystem.Update的CPU占用主要集中在3ms 以下，该值处于合理范围之内。同时，粒子系统的渲染在CPU端的开销主要集中在 0.0~1.2ms 范围内（5%~95%）。由于该游戏使用的是Unity 4.x版本，所以此处的CPU占用仍然在主线程中体现。如果您的项目使用的是Unity 5.3以后版本，那么此处的CPU占用将会为0。这是因为Unity引擎已经将粒子系统的这部分操作移植到子线程中进行。 4）UI模块 通过测试，我们发现该游戏的UI系统中，既使用了UGUI，也使用了NGUI。具体的分配是，在主UI界面中使用的是NGUI，在战斗场景中使用UGUI。其具体的CPU占用如下图所示。通过进一步分析，经过统计，NGUI模块总体在红米2上的CPU占用主要集中在0.1~3.0ms范围内（5%~95%），堆内存累积分配6.6MB；UGUI模块总体在红米2上的CPU占用主要集中在0.4~4.2ms范围内（5%~95%），堆内存累积分配4.98MB。 NGUI: UGUI: 从上图中可以看出，虽然UI模块的持续CPU占用不高，但存在离散的CPU占用高值。通过进一步分析，这些均为UI界面的Active和Deactive操作所致。下图为主UI界面和战斗副本中UI元素的具体Active情况。 NGUI: UGUI: 我们建议研发团队可以根据不同的UI界面使用频率，来尝试以下方案： 如果该UI界面开启的频率很低，那么可直接通过Instantiate/Destroy来进行切换； 如果该UI界面使用的频率较为频繁，那么可尝试通过Active/Deactive来代替Instantiate/Destroy操作，从而降低UI切换时的性能开销； 如果该UI界面使用非常频繁，则可尝试直接改变UI界面位置的方式来移进/移出相机视域体，从而来极大提升UI界面的切换效率。 因此，如果您项目中的UI开销出现了很高的离散CPU占用，那么建议您通过报告中的“资源管理”页面详细定位Instantiate/Destroy或者Active/Deactive的UI元素，并根据上述方案进行针对性的完善。 5) Instantiate实例化 目前，游戏的战斗副本中Instantiate实例化的频率很低，这说明研发团队对于GameObject的缓存操作非常注意，且进行了大量的试验和完善。下图则是游戏运行过程中，战斗副本中发现的Object实例化调用情况。该图表您可以在UWA测评报告中的“资源实例化/激活”页面中进行查看。 如果您的项目中存在较为频繁的Instantiate调用，我们的建议如下： 对于一般的GameObject（比如技能特效、怪物角色等），可将其放入缓存池并通过Active/Deactive来进行切换； 对于使用频率较高的UI界面，则可通过直接改变Transform的方式来移进移出相机视域体，可以得到更加高效的性能。 内存模块 《聚爆Implosion》在内存上的表现如下图所示。总内存峰值达到191MB，Mono堆内存峰值为13.7MB，且内存在游戏运行过程中表现较为平稳。 1) Mono堆内存 从上图可知，该游戏的总体Mono堆内存控制得非常好，在16000+帧中，Mono的堆内存峰值仅为 13.7MB，该值属于合理范围之内（<40MB）。 如此少量的Mono堆内存分配，主要得益于项目中函数堆内存分配控制得当，下图为当前游戏运行16000+帧的函数堆内存分配情况。因此，建议大家对函数代码堆内存的分配进行严格控制，对于堆内存分配较高（10000帧10MB+）的函数进行详细定位其分配原因。在UWA测评报告中，我们提供了堆内存分配Top10的具体堆栈，以方便大家尽快地定位堆内存分配出处。 2) 资源内存 经过统计，该游戏的纹理资源数量峰值为364个，内存占用峰值80.8MB。在全部纹理资源中，ETC1格式纹理占有145个，Alpha8格式纹理占有6个，RGBA32和ARGB32格式纹理共占有59个，RGB24格式纹理占有16个，其余为RGBA16格式纹理。 对于RGBA32、ARGB32和RGB24格式的纹理，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理（Android平台）进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。对于纹理资源的加载效率，我们在之前的加载模块深度解析之纹理篇中进行了详细的分析和阐述，建议大家进一步查看，以加深加载模块的掌控能力。 3) 其他资源的内存占用情况如下： Mesh资源： AnimationClip资源： AudioClip资源： 以上则为《聚爆Implosion》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、超低的堆内存分配以及引擎模块间的合理使用，足以看出该研发团队非常深厚的技术功底和对于引擎相当优秀的把控能力。 最后，非常感谢《聚爆Implosion》研发团队对 UWA 的认可和支持。感谢他们乐于将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的3D ARPG游戏在各个模块上应该做到怎样的程度。同时，也希望更多的开发团队与我们一起来分享他们的性能数据，让更多的游戏开发者受益！
今天我们为大家带来由蓝港互动研发的3D横版动作手游《王者之剑2》的 UWA测评报告分析。该游戏在各种档次的移动终端设备上，无论是画面表现力，还是性能开销都非常优异。在此，我们将对该款游戏的性能数据进行深度剖析，希望通过这篇文章可以让大家对移动游戏各个模块的运行效率有更为深刻的认知，并对大家的项目研发有所帮助。 该游戏目前在App Store已经正式上线，感兴趣的朋友可以通过http://wz.8864.com 一睹为快哦！ CPU性能 该游戏在CPU占用方面的性能非常不错，下图为该游戏在 红米Note2 设备上按照剧情进行游戏时的性能数据。可以看出，在红米Note2上运行的19636帧中，超过33ms的帧数占比为3.2%，超过50ms的帧数占比为1.7%。考虑到切换场景时资源加载的开销，一款游戏如果超过33ms的帧数占比低于10%，则说明该游戏的性能非常优秀，绝大多数时刻游戏运行非常流畅。 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。接下来，我们就详细讲解一下其CPU性能方面的亮点之处。 一. 渲染模块 通过UWA性能测评报告，我们可以看到该游戏详尽的渲染模块性能开销。该游戏在红米Note2设备上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为2.6 ms，主要集中在0.5~6.8ms范围内（5%~95%）。不透明物体渲染的CPU消耗均值为1.5 ms，主要集中在0.2~4.3ms范围内（5%~95%）。Draw Call峰值为158，且主要集中在27~119范围内（5%~95%），属于合理范围之内。 通过下图可以看出，Draw Call与Triangle的走势基本一致，在Draw Call或Triangle数值较高处，均为战斗副本中的怪物较多时出现。纵观整个游戏运行走势图，Draw Call、渲染Triangle的开销均处于合理范围之内。 二、物理模块 在UWA测评报告中，该游戏运行时的物理模块CPU开销如下图所示。可以看出，Physics.Simulate的CPU占用主要集中在1ms以下，该值处于合理范围之内（一般建议在3ms以下）。 物理模块的高效性能取决于对碰撞、Contact数量的控制得当。从下图可以看出，在游戏运行过程中，Contacts数量全部为0。同时，Active Rigidbody的数量峰值为0，碰撞体的数量峰值低于60，均处于合理范围之内。对此，建议大家时刻关注UWA测评报告中Contacts数量、Rigidbody和碰撞体数量的变化，通过对应的项目截图来判定数量高值处是否合理。 三、UI模块 该游戏在红米Note2设备上运行时的UI模块CPU开销如下图所示。该游戏使用NGUI作为UI界面的解决方案。经过统计，UI模块总体的CPU占用均值为1.8 ms，主要集中在0.1~3.5ms范围内（5%~95%）。堆内存累积分配45.7MB，平均每帧分配堆内存2.4KB。该值略高，一般我们建议平均每帧堆内存分配尽可能控制在2KB以下。 从下图中可以看出，UI堆内存的主要分配来自于UICamera.Update。该函数一般负责处理UI界面的点击操作，而一次分配较高内存，说明此处存在Instantiate实例化UI界面的操作。通过进一步查看Instantiate的详细调用开销，果然可以查看到UICamera.Update下存在较高的性能开销。 如果你的项目中也存在类似的开销，可根据UI界面使用频率的不同尝试以下方案： 1、如果该UI界面开启的频率很低，可考虑直接通过Instantiate/Destroy来进行切换； 2、如果该UI界面使用较为频繁，可尝试通过Active/Deactive来代替Instantiate/Destroy操作，从而降低UI切换时的性能开销； 3、如果该UI界面使用非常频繁，则可尝试直接改变UI界面位置的方式来移进/移出相机视域体，从而来极大提升UI界面的切换效率。 同时，关于UI界面的使用频率，这个本身没有明确的固定标准，需要大家根据自己项目的需求来进行规定。比如，通过检测游戏项目一天中UI界面的点击率来进行规划等等。 内存模块 《王者之剑2》在内存上的表现如下图所示。总内存峰值达到243MB，Mono堆内存峰值为28.2MB，且内存在游戏运行过程中表现较为平稳。243MB的总内存分配相对来说略高，研发团队可尝试在低端机器上对资源进行进一步控制，从而降低低端机器上的内存占用。 一、Mono堆内存 从上图可知，该游戏的总体Mono堆内存控制得很好，在19635帧中，Mono的堆内存峰值仅为 28.2MB。该值属于合理范围之内（<40MB）。 如此少量的Mono堆内存分配，主要得益于项目中函数堆内存分配控制得当，下图为当前游戏运行19600+帧的函数堆内存分配情况。因此，建议大家对函数代码堆内存的分配进行严格控制，对于堆内存分配较高（10000帧10MB+）的函数进行详细定位其分配原因。在UWA测评报告中，我们提供了堆内存分配Top10的具体堆栈，以方便大家尽快地定位堆内存分配出处。 经过进一步定位，该游戏在运行时Instantiate实例化操作造成较高的堆内存分配（总共累积37MB+）。因此，建议大家在查看项目报告中密切关注Instantiate实例化操作的性能开销，降低Instantiate/Destory的调用频率，将有效降低其堆内存的分配。 二、资源内存 经过统计，该游戏的纹理资源数量峰值为350个，内存占用峰值38.2MB。在全部纹理资源中，ETC1和ETC2格式纹理占有242个，Alpha8格式纹理占有9个，RGBA32和ARGB32格式纹理共占有44个，RGB24格式纹理占有18个，其余为RGBA16格式纹理。 对于RGBA32、ARGB32、RGB24和RGBA16格式的纹理，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理（Android平台）进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。对于纹理资源的加载效率，我们在之前的Unity加载模块之纹理篇中进行了详细的分析和阐述，建议大家进一步查看，来加深对加载模块的掌控能力。 其他资源的内存占用情况如下： Mesh资源： AnimationClip资源： 以上则为《王者之剑2》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、较低的堆内存分配以及引擎模块间的合理使用，足以说明该研发团队具备非常深厚的技术功底和对于引擎相当优秀的把控能力。 同时，该游戏在资源实例化和加载模块方面仍有一定的提升空间。在此，我们对其进行罗列，希望同样可以帮助到大家的研发项目。 性能优化、进无止境 一、Instantiate实例化 目前，游戏的战斗副本中Instantiate实例化的频率较高，如下图所示。较高频次的Instantiate/Destroy操作会造成一定的内存碎片，从而造成GC的加速到来。 对于频繁的Instantiate调用，我们的建议如下： 1、对于一般的GameObject（比如技能特效、怪物角色等），可将其放入缓存池并通过Active/Deactive来进行切换； 2、对于使用频率较高的UI界面，则可通过直接改变Transform的方式来移进移出相机视域体，可以得到更加高效的性能。 二、加载模块 该游戏在运行过程中，非切换场景处存在较为频繁的Loading.UpdatePreloading CPU占用，如下图红框中所示。经过进一步分析，红框中的CPU占用为UI界面开启/关闭时的Resources.UnloadUnusedAssets API函数调用开销。对此，建议研发团队密切关注加载模块中Resources.UnloadUnusedAssets的调用频率，尽可能避免较短时间该函数的重复调用。对于长时间停留在一个场景中的项目（比如MMO游戏）来说，可尝试间隔一定时间（比如15分钟甚至更长时间）来主动触发一次Resources.UnloadUnusedAssets。 以上则为该项目在后续研发中可进一步提升性能的主要方面。在我们测评过的项目中，Instantiate实例化和Resources.UnloadUnusedAssets操作调用频率过高等问题也是绝大多数研发团队遇到的共性问题。希望以上的讲解对大家的相关问题有所帮助。 最后，非常感谢《王者之剑2》研发团队对 UWA 的认可和支持。感谢他们乐于将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的3D横版动作游戏在各个模块上应该做到怎样的程度。同时，也希望更多的开发团队可以与我们一起来分享他们的性能数据，让更多的游戏开发者受益！
今天我们为大家带来由北京盖娅互娱研发的《仙剑奇侠传3D回合》 的UWA测评分析。这是一款我们深度优化的3D手游，其在中低端设备上的性能表现非常优异。在此，我们对该游戏的性能数据进行深度剖析，希望大家对手游各个模块的运行效率有更为深刻的理解。 这是侑虎科技第73篇原创文章，欢迎转发分享，未经作者授权请勿转载。同时如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。（QQ群465082844） 该游戏目前已经开启精英测试，感兴趣的朋友可以通过 https://xjqxz.gaeamobile.net/index 一睹为快，同时也将于近期正式登陆iOS平台！ CPU性能 该游戏在CPU占用方面的性能非常不错，下图为该游戏在红米Note2设备上按照剧情进行游戏时的性能数据。可以看出，在红米Note2上运行的25177帧中，超过33ms的帧数占比为9.0%，超过50ms的帧数占比为3.1%。考虑到切换场景时资源加载的开销，一款游戏如果超过33ms的帧数占比低于10%，则说明该游戏的性能非常出色，绝大部分时刻运行也会非常流畅。 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。下面，我们就详细讲解一下其CPU性能方面的亮点。 1. 渲染模块 通过UWA性能测评报告，我们可以看到该游戏详尽的渲染模块性能开销。该游戏在红米Note2设备上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为 3.4 ms，主要集中在 1.0~7.4ms 范围内（5%~95%）。不透明物体渲染的CPU消耗均值为 2.8 ms，主要集中在 1.1~6.4ms范围内（5%~95%）。Draw Call峰值为 791，且主要集中在 48~254 范围内（5%~95%）。 需要说明的是，Draw Call峰值 和 Triangle峰值 并不是判断项目存在渲染性能问题的唯一标准。建议开发团队将峰值和主要范围（5%~95%）结合起来进行判断。 Draw Call使用略高，从图中可以看出，Draw Call峰值出现在场景切换处，然后迅速降低到200左右，这是因为场景的资源在动态加载后通过StaticBatchingUtility API来手动进行合并。这是一个较为好用的降低Draw Call的方法，特别适用于对于动态加载资源、灵活拼合Mesh的项目需求。 在游戏运行过程中，我们也会偶尔看到Draw Call达到400以上，通过定位，这些Draw Call的升高均是因为剧情需要，或平视镜头进行NPC对话，或“御剑飞行”从更高的角度来俯瞰场景。对于这种情况，我们建议可以通过Culling Distance去除一些场景中的小物件（花草）或者较为耗时的物件（粒子特效）等，从而来降低因渲染场景变大而带来的额外开销。 2. 物理模块 在UWA测评报告中，该游戏运行时的物理模块CPU开销如下图所示。可以看出，Physics.Simulate的CPU占用主要集中在1ms以下，该值处于合理范围之内（一般建议在3ms以下）。 该模块的优秀效率取决于项目对碰撞对Contacts数量的控制，从下图可以看出，在游戏运行过程中，Contacts数量的峰值仅为1。同时，Active Rigidbody的数量峰值为1，碰撞体的数量峰值低于40，均处于合理范围之内。对此，建议大家时刻关注UWA测评报告中Contacts数量、Rigidbody和碰撞体数量的变化，通过对应的项目截图来判定数量高值处是否合理。 3. 动画模块 在UWA测评报告中，该游戏运行时的动画模块CPU开销如下图所示，目前该项目使用的是Mecanim动画系统。通过统计，Animator.Update总体的CPU占用均值为1.2 ms，主要集中在0.5~2.4ms范围内（5%~95%），该值处于合理范围之内（一般建议在3ms以下）。 重要提示：动画模块的优化主要有以下几点需要注意 1.对蒙皮网格在尽可能保证视觉效果的前提下进行简化，可以通过SimpleLOD等插件来快速查看简化效果； 2.除对蒙皮网格进行控制外，UWA仍强烈建议大家尽可能开启“Optimize GameObject”这一选项，它将进一步提升项目的动画模块效率； 3.控制场景中具有Animator Controller组件的GameObject，建议通过调整其Culling选项来降低视域体或一定范围外的动画组件更新。 4. UI模块 该游戏在红米Note2设备上运行时的UI模块CPU开销如下图所示。该游戏使用UGUI作为UI界面的解决方案。经过统计，UI模块总体的CPU占用均值为1.1 ms，主要集中在0.1~3.2ms范围内（5%~95%）。 目前，大量项目的UI模块CPU占用均很高。我们看到的UI模块开销，经常是如下图一般的高开销、高占用： 对于UGUI的性能优化，我们建议你时刻注意以下几点： 1.尽可能将静态UI元素和动态UI元素分开，存放于不同的Canvas下。同时，对于不同频率的动态元素也建议存放于不同的Canvas中; 2.严格控制一个非静态的Canvas（即Canvas中会有元素发生变化）中的UI元素数量，因为Canvas中所有的UI元素都会合并到一个Mesh中，一旦某个元素发生变化，则会引起Mesh发生变化，从而造成开销； 3.尽可能减少Mask组件的使用，不仅提高绘制的开销，同时会造成Draw Call明显上升。 内存模块 《仙剑奇侠传3D回合》在内存上的表现如下图所示。总内存峰值达到241MB，Mono堆内存峰值为36.3MB，且内存在游戏运行过程中表现较为平稳。241MB的总内存分配相对来说略高，研发团队可尝试在低端机器上对资源进行进一步控制，从而降低低端机器上的内存占用。 1. Mono堆内存 从上图可知，该游戏的总体Mono堆内存控制得很好，在29075帧中，Mono的堆内存峰值仅为 36.3MB。该值属于合理范围之内（<40MB）。同时，该游戏运行时触发GC的频率很低，为968帧/次。 如此低频的GC触发和少量的Mono堆内存分配，主要得益于项目的函数堆内存分配控制得非常少，下图为当前游戏运行25000+帧的函数堆内存分配情况。因此，建议大家对函数代码堆内存的分配进行严格控制，对于堆内存分配较高（10000帧10MB+）的函数进行详细定位其分配原因。在UWA测评报告中，我们也提供了堆内存分配Top10的具体堆栈，以方便大家尽快地定位堆内存分配出处。 2. 资源内存 经过统计，该游戏的纹理资源数量峰值为343个，内存占用峰值40.4MB。在全部纹理资源中，ETC1格式纹理占有179个，Alpha8格式纹理占有133个，RGBA32、ARGB32和RGB24格式纹理共占有20个，ETC2格式纹理有2个，其余为RGBA16格式纹理。 对于RGBA32、ARGB32和RGBA16格式的纹理，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理（Android平台）进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。对于纹理资源的加载效率，我们在之前的加载模块性能—纹理篇中进行了详细的分析和阐述，建议大家进一步查看，进一步加深加载模块的掌控能力。 其他资源的内存占用情况如下： Mesh资源： AnimationClip资源： AudioClip资源： 目前，该游戏运行过程中仍然能检测到少量的“疑似”冗余资源。下图分别为纹理资源、动画资源和Shader资源的冗余情况。就我们目前深度优化过的项目来看，资源冗余往往是AssetBundle的冗余打包所致。对此，如果你的项目也在使用AssetBundle来加载资源，建议将AssetBundle文件提交到UWA资源检测工具中，可以快速定位和修复AssetBundle文件中资源的冗余问题。 以上则为《仙剑奇侠传3D回合》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、低频的GC调用、较低的堆内存分配和合理的资源使用，足以说明该研发团队具备非常深厚的技术功底和对于引擎相当优秀的把控能力。 最后，非常感谢《仙剑奇侠传3D回合》研发团队对 UWA 的认可和支持。感谢他们乐于将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的3D移动游戏在各个模块上可以做到怎样的程度。同时，也欢迎更多的开发团队可以与我们一起来分享你们的性能数据，让更多的游戏开发者受益！
今天我们为大家带来由广州诗悦研发的3D回合制策略手游《星辰奇缘》的测评报告分析。这是一款我们深度优化的3D移动游戏，其在中低端设备上的性能表现非常优异。在此，我们将对该款游戏的性能数据进行深度剖析，希望通过这篇文章可以让大家对移动游戏的运行性能有更为深刻的认知，并对大家的项目研发有所帮助。 这是侑虎科技第60篇原创文章，欢迎转发分享，未经作者授权请勿转载。同时如果您有任何独到的见解或者发现也欢迎联系我们，一起探讨。（QQ群465082844） CPU性能 该游戏在CPU占用方面的性能非常不错，下图为该游戏在 红米Note2不停打怪时的性能开销。可以看出，在红米Note2上运行的29075帧中，超过33ms的帧数占比为1.3%，超过50ms的帧数占比为0.5%。 其整体CPU性能的优秀表现与其各个模块的合理使用是分不开的。下面，我们就详细讲解一下其CPU性能方面的亮点之处。 1. 渲染模块 该游戏在红米Note2设备上运行时的渲染模块CPU开销如下图所示。通过统计，半透明物体渲染的CPU消耗均值为 5.9 ms，主要集中在 3.1~9.9ms 范围内（5%~95%）。不透明物体渲染的CPU消耗均值为 2.0 ms，主要集中在 1.4~3.1ms范围内（5%~95%）。Draw Call峰值为 191，且主要集中在 91~155 范围内（5%~95%），该值处于合理范围之内。 从上图可以看出，游戏打怪过程中渲染模块的主要开销为半透明渲染所占据。究其原因，其主要是技能特效播放时的粒子特效所致，如下图所示。 粒子系统是目前大量项目中半透明渲染耗时较高的“罪魁祸首”。如果你的项目半透明渲染较高，一定要重点查一下粒子系统的渲染开销。一般来说，建议将粒子系统的渲染开销主体范围（5%~95%）控制在0~3ms范围内。 2. 动画模块 该游戏运行时的动画模块CPU开销如下图所示，目前该项目使用的是Mecanim动画系统。通过统计，Animator.Update总体的CPU占用均值为1.3 ms，主要集中在0.8~2.4ms范围内（5%~95%），该值处于合理范围之内（一般建议在3ms以下）。MeshSkinning.Update总体的CPU占用均值为0.8 ms，主要集中在0.4~1.3ms范围内（5%~95%），该值同样处于合理范围之内（一般建议在3ms以下）。 动画模块的低效能开销主要得益于研发团队对于蒙皮网格的控制。该项目中，角色模型的顶点数均在1300以下，且没有多余的顶点属性，这足以说明该研发团队在资源制作上严格的把控能力。 重要提示：除对蒙皮网格进行控制外，UWA仍强烈建议大家尽可能开启“Optimize GameObject”这一选项，它将进一步提升项目的动画模块效率。 3. UI模块 该游戏在红米Note2设备上运行时的UI模块CPU开销如下图所示。该游戏的UI模块效率经优化后已经非常出色，经过统计，UI模块总体的CPU占用均值为1.0 ms，主要集中在0.2~3.4ms范围内（5%~95%），在29000帧+的测试时间内，累积堆内存分配总值仅为1.3MB。 目前，大量项目的UI模块CPU占用均很高。我们看到的UI模块开销，经常是如下图一般的高开销、高占用。 对于UGUI的性能优化，我们建议你时刻注意以下几点： 1、尽可能将静态UI元素和动态UI元素分开，存放于不同的Canvas下。同时，对于不同频率的动态元素也建议存放于不同的Canvas中; 2、严格控制一个非静态的Canvas（即Canvas中会有元素发生变化）中的UI元素数量，因为Canvas中所有的UI元素都会合并到一个Mesh中，一旦某个元素发生变化，则会引起Mesh发生变化，从而造成开销； 3、尽可能减少Mask组件的使用，不仅提高绘制的开销，同时会造成Draw Call明显上升。 4. Shader加载 该游戏目前在运行过程中几乎不存在任何Shader解析开销。下图为游戏优化前后Shader加载的耗时对比（上图为优化前开销，下图为优化后开销）。不难看出，该游戏在优化前存在较大量的Shader重复加载开销，而在优化后则仅在开始处加载一次，后续运行则再没有Shader的加载耗时。对于Shader的加载性能分析及优化方案，我们在刚刚推出的加载模块之Shader资源中有详细说明，感兴趣的可以进一步阅读。 内存模块 《星辰奇缘》在内存上的表现同样突出，如下图所示。总内存峰值为128MB，Mono堆内存峰值为23.6MB，且内存在游戏运行过程中表现平稳。 1. Mono堆内存 从上图可知，该游戏的总体Mono堆内存控制得很好，在29075帧中，Mono的堆内存峰值仅为 23.6MB。该值属于合理范围之内（<40MB）。 该游戏Mono堆内存分配之所以可以控制得如此之小，主要得益于项目的函数经过了大量的检测和深度的优化，下图则为当前游戏运行29000+帧的函数堆内存分配情况。 2. 资源内存 经过统计，该游戏的纹理资源数量峰值为393个，内存占用峰值18.9MB。在全部纹理资源中，ETC1格式纹理占有199个，RGBA16格式纹理有42个，ARGB32格式资源数共有61个，ETC2格式纹理有22个，其余为n/a纹理（代码生成的纹理）。 对于RGBA32、RGBA16和RGB24格式的纹理，我们建议在视觉效果可以保证的情况下，尽可能使用ETC1格式纹理进行替换，不仅可以达到更小的内存占用，同时可以获得更快的加载效率。对于纹理资源的加载效率，我们在之前的加载模块性能文章中进行了详细的分析和阐述，建议大家进一步查看，进一步加深加载模块的掌控能力。 3.其他资源的内存占用情况 Mesh资源： AnimationClip资源： AudioClip资源： 以上则为《星辰奇缘》游戏在CPU性能和内存管理方面的具体使用情况。优秀的CPU性能、较低的内存分配和合理的资源使用，足以说明该研发团队具备非常深厚的技术功底和对于引擎相当优秀的把控能力。 最后，非常感谢《星辰奇缘》研发团队对 UWA 的认可和支持。感谢他们乐于将项目性能数据与大家一起分享，让更多的研发团队了解到一款性能优秀的3D回合策略游戏在各个模块上应该做到怎样的程度。同时，也希望更多的开发团队可以与我们一起来分享他们的性能数据，让更多的游戏开发者受益！