资讯
展览资讯 大型展会 灯光节 大型盛典 赛事 中标捷报 产品快讯 热门话题 艺术节 活动 演出 新闻 数艺报道 俱乐部签约
观点
大咖专访 观点洞察 书籍推荐 吐槽 设计观点 企业访谈 问答 趋势创新 论文 职场方法 薪资报价 数艺专访
幕后
幕后故事 团队访谈 经验分享 解密 评测 数艺访谈
干货
设计方案 策划方案 素材资源 教程 文案资源 PPT下载 入门宝典 作品合集 产品手册 电子书 项目对接
  • 0
  • 0
  • 0

分享

如何使用 Unity 和 Arm 分析工具解决移动端游戏性能问题(上篇)

原创 2022-03-17

本文将探讨如何使用 Unity 和 Arm 分析工具来找出手机游戏中存在的性能问题。此外还有一些优化游戏内容的最佳方法。 


要找出游戏中存在的性能问题,首先应在不同的设备上对它进行测试。而最好的方法则是在一台真实设备上运行,然后收集它的性能情况。诸如 Unity Profiler 和 Frame Debugger 之类的工具能够帮助用户深入了解游戏软件是如何调用资源的。此外, Arm Mobile Studio 一类的工具则能从设备上捕获性能计数器的活动数据,从而让用户准确地了解游戏运行过程中CPU 和GPU 资源的使用情况。


Unity Profiler:

https://docs.unity.cn/cn/current/Manual/Profiler.html


Frame Debugger:

https://docs.unity.cn/cn/current/Manual/FrameDebugger.html


Arm Mobile Studio:

https://developer.arm.com/tools-and-software/graphics-and-gaming/arm-mobile-studio


笔者使用的设备中包含了一块 Mali GPU,但本文的观点也适用于采用其他 GPU 的移动设备。


测试示例


笔者测试的是一款 ARPG 游戏。在游戏中,玩家要通过近战和法术攻击对抗一波又一波不断来袭的敌人。随着屏幕中出现的敌人数量越来越多,粒子数量显著增加,视觉效果后期处理也愈发复杂。很快,GPU 就不堪重负。 



用Unity Profiler和

Frame Debugger进行分析


接下来,笔者用 Unity Profiler 运行游戏,来观察设备是否出现性能下降。很快,笔者就发现了一些重要的问题,如后处理效果、固定时间步长和实例化峰值。


  后处理


后处理效果是导致游戏运行过程中 CPU 性能不佳的主要原因。 


后处理效果:

https://docs.unity.cn/cn/current/Manual/com.unity.postprocessing.html


渲染摄像机耗费时间巨大,并且会超越帧数限制。


其中,能使游戏场景中的明亮区域发光的光晕效果带来的负担最大。


从上面的屏幕截图中可以看出,渲染相机耗费时间巨大,并且会超越帧数限制。主线程等待渲染命令完成后才能准备下一帧。接下来让我们使用 Unity Frame Debugger 来对问题进行进一步的分析。


在设备上以全屏分辨率查看 Frame Debugger


首先要注意到的是,游戏是在设备的全屏分辨率下进行渲染的。考虑到游戏内容的复杂性,这会给普通移动设备的 GPU 带来过度的压力。 将分辨率降低到 1080p 甚至 720p 这样更合理的水平,可以显著降低游戏渲染,特别是后期处理效果的成本。


查看Bloom(光晕)效果的绘制调用


接下来要观察的是光晕处理过程中,有 25 个光晕效果的绘制调用。每次绘制调用均代表一个目标缓冲区,其大小从设备全屏分辨率的一半开始。此后,每次迭代时该分辨率减半。降低初始渲染分辨率是减少潜在迭代次数的一种方法。


另一种选择是修改光晕效果源代码来减少迭代次数,并设置一些合理的限制。由于处理这些效果需要花费大量的时间,因此在这种情况下,最好暂时禁用后处理效果。至少在能够保证游戏的其他部分以每秒 30 帧的帧率平稳运行之前,不要使用后处理效果。 


  固定时间步长


此项目的另一个改进是减少固定时间步长间隔的频率。


可以发现,目前固定时间步长间隔的频率足够短,可以在一帧中多次调用;默认情况下,Unity 将其设置为 0.02 或 50Hz。对于目标为每秒 30 帧的手游,可以尝试将时间步长设为 0.04。因为当时间步长为 0.333 时,如果要将帧率维持在30 帧,那么就可能出现某一帧用时特别长,导致在下一帧中要进行两次调用。这就意味着需要更长的时间,而一帧用时变长将成为恶性循环,无法打破。用户还可以设置允许的最大时间步长来阻止某帧用时过长,挤占后续帧的时间。


时间步长:

https://docs.unity.cn/cn/current/Manual/class-TimeManager.html


此时间步长的持续时间会给使用 Fixed Update 函数的脚本,以及以固定间隔更新的 Unity 内部系统带来影响,例如物理效果和动画。


设定固定时间步长后的时间线


就本项目而言,只有物理和 Cinemachine 插件对时间耗用影响较大,每次调用大约需 3 毫秒;一次调用意味着系统已完全更新(尽管额外调用 5 次就意味着每帧浪费的时间会达到 15 毫秒)。


Cinemachine 插件:

https://docs.unity.cn/cn/current/Manual/com.unity.cinemachine.html


FixedUpdate.PhysicsFixedUpdate由于后期处理效果而变慢


这是由于后期处理效果缓慢导致的。对此,前文提到通过减少固定时间步长频率来为 CPU 减轻不必要的负担,该建议仍然有效,此外关闭物理和 Cinemachine 插件也可以减少时间消耗。 


  实例化峰值


在分析期间,可以在帧时间内看到峰值。在 CPU 分析器的层次结构视图中跟踪峰值后,可以发现它们源于 NPC 的实例化。 


在 CPU 分析器的层次结构视跟踪实例化峰值


对此最常见的解决方案是,提前实例化角色并将它们闲置于对象池中。然后从对象池中抓取这些 NPC,这样就消除了实例化成本。如果需要更多 NPC,可以根据需要扩展对象池。 


对象池:

https://learn.unity.com/tutorial/introduction-to-object-pooling


同样的问题也会在使用技能时出现,因为该行为也在实例化对象。  


CPU 实例化峰值


对象池是解决这些问题最简单的方法。尽管加载时间可能会受到影响,但在运行时可以获得更加平滑的帧速率,在此例中,使用对象池方案是两害相较取其轻的选择。 


通过 Arm Mobile Studio 进行分析


我们还使用 Arm Mobile Studio 深入了解了游戏的行为。使用 Arm Mobile Studio 中的工具,我们能够获得 CPU 和 GPU 的性能计数器活动数据,由此我们可以清楚地看到游戏如何使用移动设备的资源。 


你可以下载免费的 Arm Mobile Studio。共包含 4 个工具:


 Performance Advisor:用于生成易读的报告,并提供优化建议
 Streamline:一个全面的性能分析器,用于捕获所有计数器活动
 Mali Offline Compiler:用于检查着色器程序在 Mali GPU 上的运行情况

 Graphics Analyzer:用于调试图形 API 调用并分析内容的渲染情况


下载 Arm Mobile Studio:

https://developer.arm.com/tools-and-software/graphics-and-gaming/arm-mobile-studio/downloads


01  Performance Advisor


为我们提供游戏性能的快速小结,旨在用于定期的性能检查。


它能够快速生成报告,特别是如果你将其构建到持续集成工作流中,并与每晚构建系统一起运用时,它的速度优势将会更加明显。为我们提供游戏性能的快速小结,旨在用于定期的性能检查。它能够快速生成报告,特别是如果你将其构建到持续集成工作流中,并与每晚构建系统一起运用时,它的速度优势将会更加明显。 


Performance Advisor -收集摘要


在游戏的前 2 分钟内,Performance Advisor 显示我们的平均帧数为每秒 17 帧。帧率分析图表开头的绿色部分表示游戏正在加载阶段,然后图表突然变为蓝色,表示游戏在疲于处理片段(Fragment),并且始终保持这种状态。该现象意味着设备中的 GPU 正在努力处理片段工作负载,这表明游戏所需的工作量过大,或是游戏未能有效地处理像素。 


我们在游戏中添加了区域注释,帧速率分析图表显示了我们自定义的区域名称。在图表标有“S,”标记的地方,Performance Advisor 截取了游戏的屏幕截图来帮助我们了解当时游戏画面如何。你可以配置在帧数低于指定值时进行屏幕截图。此时由于每秒帧数始终保持较低值,Performance Advisor 将以每 200 帧的默认间隔截取屏幕截图。


让我们来看看每帧 GPU 循环数的图表,我们为此设备添加了每帧 2800 万个循环的预算 。在帧速率为每秒 30 帧的前提下,我们估计这是该设备能够处理的最大循环数。我们能够发现 GPU 的循环数明显超出了这个预算,并且循环数随着时间的推移而增加。


Performance Advisor - 每帧 GPU 循环数


Performance Advisor 在发现问题时可以提供优化建议。从每帧着色器循环数图表中,我们可以看到执行引擎循环的数量较高。在 Mali 着色器核心中,执行引擎负责处理算术运算。Performance Advisor 已将此标记为一个问题,并建议我们减少着色器中的计算。


Performance Advisor - 每帧着色器循环数


对此有一个简单的解决方法。你可以将着色器变量的精度由 highp 调整为 mediump,这种调整对画面不会有明显影响,但可以显著减少着色器运算消耗。关于如何执行此操作的信息,请参阅我们文档中的“着色器数据类型和精度”章节。此外,正如我们在前文中讲到 Unity Frame Debugger 时提到的,游戏当前正在以设备的全屏分辨率进行渲染。我们为降低游戏渲染分辨率(降低至 1080p 或 720p)所做的任何更改也将降低片段着色成本。 


  内容指标


我们为此设备设定了每帧 500,000 个顶点的预算。而在大约 45 秒内就超出了这个预算,顶点数量也随着时间的推移稳步增加。


Performance Advisor - 每帧顶点数


查看每帧图元数图表可知,尽管可见图元的数量保持相对不变,但处理的图元总数也在随着时间的推移而增加。在游戏的前 2 分钟内,唯一创建的新对象是敌方 NPC,而它们很快就被英雄消灭了。这表明即使敌人被消灭,它们的几何图形仍然存在- 尽管它们并不可见。


Performance Advisor - 每帧图元数


GPU 无法处理游戏需求的原因多种多样,因此我们需要进一步利用 Arm 分析工具— Streamline。Streamline 能让我们更深入地了解这种繁重的片段工作负载,此外,通过查看其他计数器,可以找到减少负载的方法。


02  Streamline 分析


在 Streamline 中查看游戏的同一部分,我们可以绘制出一系列图表,这些图表显示了几何图形和像素处理不同阶段的 GPU 计数器活动。这些图示阐明了 GPU 是如何处理游戏内容的,以及是否进行了不必要的处理。


Mali GPU 采用基于图块的方法来处理图形工作负载,其中屏幕空间被分成多个图块,每个图块按顺序处理完成。首先对每个图块执行几何处理,然后在像素处理期间为像素着色。


Mali GPU 正在处理图形工作负载


我们已知设备中的 GPU 已被片段工作负载耗尽,因此需要寻找能够减轻像素处理阶段负荷的方法。


其中一种减轻像素处理负荷的方法是从一开始就降低需要像素处理的几何图形的复杂性。在像素处理之前,完全关闭屏幕外或背面的几何形状;但是仅部分覆盖 2x2 像素四边形的小三角形会降低片段效率,并且每个输出像素具有较高的带宽成本。 


Streamline 中的 Mali 几何使用率和 Mali 几何剔除率图表显示了 GPU 处理几何图形的有效性。我们可以看到发送到 GPU 的图元数量,以及在几何图形处理过程中剔除的图元数量。在此阶段剔除的内容将不会继续进行像素处理。虽然这样很好,但我们还可以更有效地组织内容,使不可见图元完全不会发送出去。


Streamline 中的 Mali 几何使用率和 Mali 几何剔除率图表


在 Mali 几何使用率 图表中,我们可以看到,107 万个图元在所选时间范围(约0.05 秒)内进入几何处理(橙色线),但在此阶段剔除了 70 万个图元(红线)。


Mali 几何剔除率图表显示了它们被剔除的原因。大约有一半图元是通过正/背面测试(橙线)剔除的,由于这些是 3D 物体背面的三角形,因此被剔除也在预期之中。更重要的是,31.9% 的图元由样品测试(紫线)剔除的,而在理想情况下,这个数值应当小于 5%。样品测试表明,这些图元太小而无法栅格化,未能达到单个样本点,因此被认为是不可见的。当具有复杂网格的对象远离相机时,网格中的三角形太小而不可见,这种情况就可能发生。较高的数值表明游戏对象在屏幕上的位置很远,其网格却过于复杂。  


对于大到足以通过样本测试但仍然只覆盖几个像素的图元,这个问题更加棘手。这些“微三角形”被发送进行像素处理,而处理成本又很高。这是由于在片段着色过程中,三角形被栅格化为 2×2 像素的补丁,称为四边形。微三角形只占据四边形内的一部分像素,但必须将整个四边形发送进行处理。这意味着片段着色器将在硬件中使用空闲通道运行,从而降低着色器的执行效率。


微三角形占据四边形内的一部分像素


为了检查是否存在微三角形问题,我们可以使用 Streamline 中的 Mali 核心工作负载属性图表来监控覆盖效率。理想情况下,该数值应小于 10%。我们可以看到,在某些部分中,部分覆盖率(绿线)非常高,甚至超过 70%。该数值表明内容中包含高密度的微三角形,证实了前文强调的高样本剔除率问题。


Mali 核心工作负载属性图表展开


最终出现在屏幕上的几何体需要根据其位置适当调整大小。远端的复杂布景对场景意义不大,无需详尽呈现。我们可以使用细节层次 (LOD) 网格处理这些远离相机的对象,减小其复杂性,节约处理能力与 DRAM 带宽。或者不使用几何体,改用纹理和法线贴图为对象构建表面细节。 


细节层次(LOD) 网格:

https://docs.unity.cn/cn/current/Manual/LevelOfDetail.html


  分析着色器

通过 Performance Advisor 的报告,我们发现着色器成本过高,因此可以通过降低它们的精度进行优化。在 Streamline 中,我们可以使用 Mali 使用变化图表来查看使用 32 位(高精度)或 16 位(中等精度)插值时的循环数。我们可以看到大多数循环使用了 32 位插值。16 位变量的插值速度是 32 位变量的两倍,存储插值结果所使用的着色器寄存器空间也仅为后者的一半,因此我们建议尽可能在片段着色器中使用 mediump(16 位)变化输入。


Mali Offline Compiler 着色器分析




在下篇中,我们会继续为大家带来使用 Mali Offline Compiler 进行着色器分析、使用 Graphics Analyzer 进行图形 API 调用分析,以及游戏优化的内容和具体做法。


本教程已经发布在 Unity 社区中,欢迎大家点击“阅读原文”跳转学习。


长按关注

Unity 官方微信

第一时间了解Unity引擎动向,学习最新开发技巧

阅读原文

* 文章为作者独立观点,不代表数艺网立场转载须知

本内容由数艺网主动采集收录,信息来源为 “Unity官方平台” 公开网络发布内容。第三方如需转载本内容,必须完整标注原作者信息及 “来源:数艺网”,严禁擅自篡改、删减或未标注来源转载。 并附上本页链接: 若您的内容不希望被数艺网收录,或认为此举侵犯了您的合法权益,敬请通过微信 ID:d-arts-cn 联系数艺网。我们将致以诚挚歉意,并第一时间为您办理下架或删除处理。

数字媒体艺术 新媒体艺术 科技艺术 作品分享 科技前沿

20323 举报
  0
登录| 注册 后参与评论