详解如何使用UWA GOT Online优化Unity微信小游戏UWA全新发布了针对微信小游戏的性能优化解决方案。其中UWA GOT Online服务提供了优化CPU耗时、资源管理和启动耗时等功能。下面我们详细说明具体的使用方式以及UWA提供的优化经验 。
Overview模式主要分析项目运行时的性能问题。在遇到卡顿,加载缓慢的时候,我们就要从这个模式定位。在这里我们可以看到性能相关的多项关键指标:FPS、Jank、Reserved Total、耗电量。
这些优化建议都是来自于各类核心参数的萃取。 建议团队在分析问题时,开启“堆栈获取”功能,从而获得更深度的性能参数。
以UI模块为例,开发者可以在总体性能趋势的UI模块性能页下,查看Canvas.SendWillRenderCanvases、Canvas.BuildBatch等重点函数的耗时和调用情况,快速对UI模块的性能情况进行一个基本的掌握。
如果想要更深入地分析模块中的函数,可以展开下方的UI模块函数堆栈。 UWA对优化过程中经常出现的函数进行了标注,并且在表格中详细列出了函数的耗时、占比以及调用次数等信息。 此外,开发者还可以利用操作面板,在自定义面板中方便地查看每个函数的CPU耗时和调用次数情况,从而更全面地了解函数的性能表现。
卡顿分析下的卡顿点分析,展示出了报告中所有卡顿点的分布、耗时等信息,开发者可以在这个页面快速概览项目的卡顿情况。
开发者可以结合卡顿函数堆栈冰柱图和卡顿函数列表,对卡顿帧函数的耗时占比、调用关系进行分析,定位造成卡顿问题最大的函数。
在这个页面下,详细统计了对应的函数堆栈信息,包括耗时占比、具体耗时与调用次数等数据,开发者可结合卡顿帧的Timeline信息,对每个造成卡顿的函数进行进一步下探。
在重点函数分析页签下,UWA对测试过程中容易发生卡顿的重点函数进行了分类和整合,包括了GC、Unload Unused 、加载、动画 、物理 五类卡顿。 报告中展示了这些重点函数的调用频率和卡顿点,开发者可以更加高效地排查项目中的卡顿情况,定位卡顿原因。
闪退已经是小游戏性能的杀手之一,直接决定了项目的生死线。 为此我们也提供了内存分析模块。 如下图,报告中展示了Reserved Total、Reserved Mono、资源内存占用的走势,便于我们快速判断是否存在内存泄漏的可能。
在自定义模式下开云电竞官网入口,UWA SDK会同时采集包括纹理、网格、动画、音频等主流资源的数量和内存占用情况,开发者可以关注这些资源的内存占用是否合理。
当资源内存占用情况超出预期后,开发者就可以通过Resource模式或在Overview模式下开启Resource资源采集,对这些资源的具体参数进行进一步分析。
在Resource模式下,UWA SDK会对上述的纹理、网格、动画、音频共11项资源进行更细致的数据采集。除了通用的内存、数量、生命周期外,针对不同类型的资源也定制了更详细的检测项规则。以纹理资源为例,就包括纹理尺寸、压缩格式、是否开启R/W、Mipmap等。
在资源名称列,UWA也会对常驻资源、疑似冗余资源、疑似泄漏资源进行标记,以便快速定位问题资源。
除了查看所有资源外,开发者也可以切换至指定帧,查看所选帧资源的具体信息。 或者通过对比模式,结合两帧间的共同资源和差异资源判断资源的加载、卸载情况。
以下是UWA在小游戏的性能优化过程中,CPU模块、内存占用相关的优化经验,希望对正在使用Unity引擎开发微信小游戏的团队有所帮助。
通过查看函数调用次数曲线,可以清晰 地 知道脚本函数的调用次数,如下图中的EntityStateMachine.Update的调用次数达到70+,针对这种情况建议使用Manager中使用for循环调用对应逻辑的方式来减少Invoke次数,从而降低开销。
在动画模块中,可以通过勾选堆栈中子函数的调用次数以及父节点的耗时,看到他们的数值趋势是正相关的,因此我们就可以通过排查每帧持续Deactive的对象是否合理来进行优化。
对于MeshSkinning.Update这个函数来说,相比APP,小游戏会有较高的开销,这是因为在APP中动画蒙皮会在Worker线程中进行,但是小游戏中没有Worker线程,因此耗时会变高很多。因此在小游戏中要尽量限制蒙皮动画的使用,对于需要使用蒙皮动画的网格也应尽量控制其顶点数量。另外,在团结引擎中有GPU Skinning相关的优化,会将耗时的CPU的部分移动到GPU中,因此会降低该函数的CPU开销。
另外,可以从小游戏的Overview报告中清晰地看到小游戏运行过程中每帧的物理更新的次数,通常在不影响游戏逻辑表现的情况下,将每帧的最大更新次数设置为5即可。下图中的最大次数为17次,这样Physics.Simulate以及MonoBehavior.FixedUpdate的逻辑代码的耗时都会有更高的开销。
在 Overview报告中,我们将一些常见的卡顿函数耗时做了归类,在这个模块中可以清晰地看到哪些函数造成了严重的卡顿,如下图中的GarbageCollectAssetsProfile函数,该函数在游戏运行过程中有非常频繁的高耗时,说明在游戏过程中有非常多的Resources.UnloadUnusedAssets的调用,这个操作是非常不合理的,需要尽量避免频繁的调用该函数。
在小游戏的iOS高性能模式中,会有每10秒由WX进行的GC造成的卡顿,该卡顿的耗时会被统计到WaitForTargetFPS函数,如下图函数中的耗时峰值。 为了减少这个卡顿情况,可以考虑增大unity-namespace.js中iOSAutoGCInterval的数值,并在C#脚本中在合适的时机主动调用WX.triggerGC。
在内存模块中,可以直观地看到Mono内存的走势,其中需要关注的是峰值以及初始的堆内存占用,如果初始占用就达到较高的数值,说明配置表需要进一步优化。 更进一步的堆内存分配细节,建议使用GOT Online的Mono模式对游戏的APP版本进行测试来获取,这样可以定位到具体的分配信息,如哪些函数有持续分配或者峰值分配,从而精准地优化堆内存分配。
在小游戏制作时应尽量控制纹理内存,在Resource模式中,我们可以非常详细的看到纹理内存的占用走势,以及单帧内存中的纹理资源详情,如下图中单帧纹理内存最多占用152.16MB,从单帧的详情可以看到主要是有非常多的纹理没有进行压缩,使用的是RGBA32格式,因此需要对这些未压缩的纹理进行ASTC压缩。
在小游戏制作中,应该尽量减少RenderTexture的使用,在Resource模式中通过详细的资源内存走势曲线,可以找到内存不合理的地方,从单帧详情可以看出来内存中的RT是否可以再进一步的优化,如下图中的后处理相关的RT,以及CameraDepthTexture是否可以进一步地移除。