性能优化是游戏项目开发中一个重要环节。游戏帧率过低,手机发烫, 包体太大,低端机上跑不起来等, 这些都需要来做优化,不管过去,现在,未来,性能优化都是永恒的话题。
而性能优化首先要掌握的是性能分析,通过分析才能发现问题所在。性能分析对于游戏开发是必备的,通过性能分析工具可以给我们提供游戏性能表现的详细信息。如果我们的游戏存在性能问题,如低帧率或者高内存占用,性能分析工具可以帮助我们发现问题的起因,并协助我们解决问题。
开始之前,有关性能分析需要了解的概念:
FPS(帧率)
FPS是衡量游戏性能的基本指标。在游戏中,一帧类似于动画中的一帧,FPS是指游戏运行时每秒所运行的帧数,也可以理解为每秒渲染的画面数。
通常FPS越高,表明游戏性能运行越好,对于大多数当前游戏的目标是帧率60FPS,通常来说,帧率在30FPS以上是可以接受的,特别是移动游戏,或者不需要快速反应互动的游戏,对于在VR游戏中,则至少需要90FPS。
实际上FPS并不是衡量游戏稳定体验的理想指标。考虑以下情况:在运行时的前0.75s内渲染了59帧。然后接下来的1帧需要0.25s才能渲染完毕。虽然是60fps,但实际上会让玩家感觉卡顿。对于我们来说更有用的是渲染一帧需要多少毫秒。
渲染一帧,Unity必须执行很多不同的任务。简单的说,Unity必须更新游戏的状态,获取游戏的快照并且把快照画到屏幕上。有一些任务是在每一帧都执行的,包括读取用户输入,执行脚本,运行光照计算等。除此之外,有许多操作是在一帧执行多次的,例如物理运算。当所有这些任务都执行的足够快时,我们的游戏才会有稳定且可接受的帧率。当这些任务执行的不够快时,渲染一帧将花费太长的时间,并且帧率会因此下降。
知道哪些任务花费了太长的时间执行,对于我们怎样去解决性能问题是十分关键的。一旦我们知道了哪些任务降低了帧率,我们就可以尝试去优化游戏的那一部分。这就是为什么性能分析工具这么关键:性能分析工具告诉我们在一帧中每个任务花费了多长时间。
VSync(垂直同步)
VSync将应用程序的帧率与显示器的刷新速率同步。这意味着,如果您有一个60Hz的显示器,并且游戏的帧预算在16.66ms内,则它会强制以60fps运行,而不允许更快。将帧率与显示器的刷新速率同步,可以减轻GPU的负担并解决屏幕撕裂等视觉图像瑕疵。在Unity中,通过Quality settings 可以设置VSync Count (Edit > Project Settings > Quality)。
QualitySettings.vSyncCount有三种选项
- Don't Sync(不同步)
- Every V Blank(每一个垂直同步)
- Every Second V Blank(每一秒的垂直同步)
移动平台忽视 QualitySettings.vSyncCount。仅使用 Application.targetFrameRate 控制帧率。移动平台的最大帧率就是屏幕的刷新率,移动平台上的默认帧率通常为每秒 30 帧。
垂直同步对 FPS 的影响
我们平时用的电脑显示器,一般屏幕的刷新率都是80HZ上下,那么显卡会按照每秒80HZ来发送一个垂直同步信号。
- 开启垂直同步:显卡绘制完一屏图像后,需要等待80HZ垂直同步信号的到达,才可以开始绘制下一屏。这样游戏自然受到刷新率运行的制约。
- 关闭垂直同步:那么游戏中显卡绘制完一屏图像后,显卡和显示器无需等待垂直同步信号达到,就可以开始下一屏的绘制,展示了显卡的实力。
但是不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面更加平滑和稳定。取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上势必打折扣。这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因。
Unity Profiler
Profiler是Unity内置的强大的性能分析工具,通过Profiler,我们可以了解到cpu使用情况,gpu使用情况,渲染,内存使用情况,声音,物理,网络,UI等等。还可以进行录制数据,分析每帧的运行情况。可以在Unity Editor中进行分析,也可以在目标平台上分析,连接真机,真实了解游戏运行情况。
The CPU usage profiler
当我们查看Profiler窗口的上部时,可以看到完成每帧的任务花费了多少cpu时间。
在CPU usage左侧,可以看到不同颜色的分类块,可以点击显示隐藏你感兴趣的分类,右侧显示各分类的耗时,可以根据颜色块的大小清晰的了解性能的瓶颈所在。最下面可以详细的了解所有任务的耗时,可以精确到各大个函数的耗时,可以根据排序快速定位问题所在,也可以搜索你关心的函数。
渲染分析
渲染是导致性能问题的常见原因。在尝试修复渲染问题前,确定是CPU受限还是GPU受限非常重要,这些情况需要不同的解决方法。 简单来说,CPU负责确定必须绘制什么,GPU负责绘制它。
如果游戏中因为CPU执行渲染任务耗时太久而导致帧渲染时间过长,我们称其为 CPU受限(CPU Bound)。
如果游戏中因为GPU执行渲染任务耗时太久而导致帧渲染时间过长,我们称其为 GPU受限(GPU Bound)。
GPU受限
通过GPU usage快速地判断游戏是否GPU受限。但并非所有设备和驱动程序都支持此分析器。在检查GPU受限之前,需要先检查GPU usage是否适用于我们的目标设备。如果添加GPU usage后有数据意味目标设备支持GPU usage。
如果GPU时间超过CPU时间,可以确定在该点上已经GPU受限。
如果目标硬件不支持GPU usage,仍然可以确定游戏是否GPU受限。可以通过观察CPU使用情况来判断。如果发现CPU正在等待GPU完成其任务,这意味着游戏GPU受限。
如果主线程在Profiler标记(例如Gfx.WaitForPresentOnGfxThread)中花费大量时间,而渲染线程同时显示Gfx.PresentFrame或<GraphicsAPIName>.WaitForLastPresent等标记,则应用程序出现了GPU受限。
CPU受限
如果尚未确定性能问题的原因,我们继续分析基于CPU的渲染问题。
点击选择CPU usage。
在分析器窗口的顶部,CPU usage显示其随时间变化的数据。查看表示渲染的图表中的彩色部分。可以通过在关键字中单击名称旁边的彩色方块来隐藏或显示图表中的数据。
如果一帧中大部分时间由渲染所占用,这表明渲染可能是问题的原因。可以通过以下步骤深入分析数据来确认:
查看分析器窗口底部显示当前选定帧和分析器详细信息的区域。
在该区域左上角的下拉菜单中选择“Hierarchy”。
选择“Time ms”列,按时间(毫秒)对函数进行排序。
单击列表中的顶部函数进行选择。
如果选定的函数是渲染函数,CPU分析器图表将通过Rendering进行突出显示。这种情况意味着与渲染相关的操作导致性能问题,此时游戏处于CPU受限状态。请注意函数名称和执行函数的线程,这些信息将在修复问题时很有用。
解决GPU受限时的渲染问题
优化填充率
填充率指GPU每秒能够渲染的屏幕像素数量,它是引起GPU的性能问题的最常见因素,尤其是在移动设备上。
填充率相关的优化手段:
- 优化片元着色器(Fragment Shader)
- 减少重绘(Overdraw)
- 优化减少后处理(Image Effects)
优化显存带宽(Memory Bandwidth)
显存带宽指GPU对其专用的内存的读写速率。如果游戏出现带宽受限,通常是因为使用了太大的纹理(Texture)。
优化顶点处理(Vertex Processing)
顶点处理指GPU渲染Mesh中的每个顶点使所做的工作。顶点处理的开销与两个因素有关:需要进行渲染的顶点的数量和对每个顶点所要进行的操作。
降低屏幕渲染分辨率,通常这是有效的手段。也可以通过此方法来检验是否GPU受限。
解决CPU受限时的渲染问题
向GPU发送指令的时间开销是引起CPU Bound的最常见原因,向GPU发送指令的过程中,开销最大的操作是SetPass Call。
通常,有3种 降低Batch和SetPass Call数目的方法:
- 降低需要渲染的对象的数量,可以同时减少Batch和SetPass Call。
- 降低每个对象需要被渲染的次数,可以减少SetPass Call。
- 将对象合并到更少的批处理当中,可以减少Batch。
CPU与GPU并不各自孤立:
如果 CPU 在物理计算和脚本运行要花很多时间,那么即使 Shader 优化得再好,也不会提高帧率;
如果 GPU 处理 Shader 消耗大量时间,那么即使优化物理系统和脚本也不会对提高帧率有什么帮助。
当 CPU 压力大,而 GPU 压力小时,就不应该采取一些加大 CPU 压力以减少 GPU 压力的方法。反之亦然。
因此我们要分析找到影响运行性能的短板。
垂直同步的影响
垂直同步(VSync)用来同步游戏的帧率和屏幕的刷新率。垂直同步会影响游戏的帧率,在Profiler窗口中可以看到影响。如果我们不是特别确定问题所在,垂直同步的影响可能看起来像性能问题,我们可以选择在CPU usage profiler中隐藏Vsync信息,也可以在Quality settings 关闭垂直同步。
Frame Debugger
Frame Debugger是Unity另一个常用的性能分析工具,它能够让我们详细查看某一帧的渲染过程。只需在菜单栏选择"Window > Analysis > Frame Debugger"即可打开。
在游戏运行中,点击Frame Debugger的Enable按钮,游戏将自动暂停,并在界面中展示当前帧的渲染细节。
界面左侧列表以层级视图形式显示绘制调用(DrawCall、事件等),右侧面板提供有关绘制调用的更多信息,例如几何体细节和用于渲染的着色器。
选中某一渲染步骤后,界面右侧将显示该步骤的详细信息,包括渲染的目标,使用的Shader以及Shader属性等详细信息。同时,Game视图中也会展示该步骤渲染的结果。
Frame Debugger在优化DrawCall和调试Shader时非常有用。
Memory Profiler
Memory Profiler是Unity分析内存性能的进阶工具,可描绘更全面的内存使用情况,使得性能优化与内存问题检测更为方便快捷。您可以使用它来检查Unity应用程序和Unity编辑器的内存使用情况。您可以使用它来捕获、检查和比较内存快照。快照记录了当内存分析器捕获快照时,应用程序使用的内存是如何组织的。Memory Profiler还提供本机和托管内存分配的概述,以评估应用程序的内存使用情况,并识别潜在的问题,如内存泄漏。
要避免应用在容量有限的设备上出现内存溢出崩溃的问题,那么内存优化将是非常关键的一步。此外,如果项目需要发布至多个平台,开发者则需要调整内存占用,以最大化利用每个平台。
Memory Profiler让面临这些挑战的用户能够截取并审查游戏在特定时间点的内存占用。
借助这些“快照”,你可以找出游戏中最占内存的部分或崩溃的原因。
Memory Profiler需要使用Package Manager安装,Package Manager窗口左上角点击“+”,Add pacakge by name : com.unity.memoryprofiler
Gmae View Statistics
在Unity的Game视图包括一个统计窗口,显示您的应用程序在运行模式下的实时渲染信息。要打开此窗口,请单击右上角的 Stats 按钮。该窗口会在 Game 视图右上角叠加显示。它包含的统计信息对于优化性能很有用。显示的具体统计信息根据构建目标而有所不同。
Statistics 窗口的字段信息:
- FPS:当前 Unity 每秒能够绘制的帧数
- CUP main:处理一帧所花费的总时间。包括 Unity 处理应用程序的帧更新所花费的时间,以及 Unity 在编辑器中更新场景视图、更新其他编辑器窗口或处理仅编辑器任务所花费的时间。
- CUP render thread:渲染一帧所花费的时间。这个数字包括Unity处理游戏视图的帧更新所花费的时间;它不包括Unity在编辑器中花费的时间。
- Batches:Unity 在一帧内处理的批次总数。该数字包括静态和动态批次。
- Saved by batching: Unity 合并的批次数。为确保良好的批处理,应尽可能在不同游戏对象之间共享材质。更改渲染状态会将批次分成具有相同状态的组。
- Tris:Unity 在一帧内处理的三角形数。在针对低端硬件进行优化时,这一点非常重要。
- Verts:Unity 在一帧内处理的顶点数。在针对低端硬件进行优化时,这一点非常重要。
- Screen:屏幕的分辨率及其使用的内存量。
- SetPass calls: Unity 在一帧中切换用于渲染游戏对象的着色器通道的次数。一个着色器可能包含多个着色器通道,每个通道以不同的方式渲染场景中的游戏对象。每个 pass 都需要 Unity 绑定一个新的着色器,这可能会带来 CPU 开销。
- Shadow casters:在一帧中投射阴影的游戏对象的数量。
- Visible skinned meshes:Unity 在帧中渲染的带蒙皮的网格渲染器的数量。
- Animation components playing:帧期间播放的动画数量(Animation)。
- Animatior components playing:帧期间播放的动画数量(Animatior)。
Scene View Draw Mode
在Unity的Scene视图右上角最左侧,可以改变Scene的绘制模式,不同的绘制模式有时对性能分析也有所帮助。
Shadow Cascades
使用颜色可以采用不同的级联级别显示场景的各个部分。此模式有助于正确设置阴影距离、级联计数和级联分割比率。请注意,此可视化方法会使用通常大于阴影距离的 Scene 视图远平面,因此如果要将摄像机的游戏内行为与小远平面匹配,可能需要缩短阴影距离。
Overdraw
将对象渲染为透明的“轮廓”。透明的颜色会累积,因此可以轻松找到一个对象绘制在另一个对象上的位置。颜色越亮表示Overdraw越高,可以简单的看出哪些地方过渡绘制。
比如在此模式下查看特效,如果发现特别亮,则说明此特效Overdraw过高,应考虑优化。
Mipmaps
使用颜色代码显示理想的纹理大小:红色表示纹理大于必要值(在当前距离和分辨率下) ;蓝色表示纹理可以更大。当然,理想的纹理大小取决于游戏运行的分辨率以及摄像机与特定表面的接近程度。
比如在此模式下浏览场景,如果发现有些地方特别红,则说明这个地方的贴图Mipmap不合理,可以考虑压缩贴图。
Unity是个多平台开发引擎,除了其内置的性能分析工具,也可以通过导出对应的平台工程,使用对应平台原生的性能分析工具,如android studio, xcode
除了在运行时进行性能分析,我们也可以在非运行时对资源进行检测,对性能优化也是十分有帮助的。
UWA本地资源检测
UWA,https://www.uwa4d.com 致力于游戏/VR应用性能诊断与优化,这里主要介绍下它的本地资源检测。
UWA本地资源检测是对游戏、VR等项目工程的资源、代码和设置等进行自动检测的服务,是项目研发持续集成、持续交付流程中的重要一环,旨在为游戏研发制定资源与代码规范,帮助研发团队快速发现和解决项目中的性能问题以及可能出现的异常、错误。研发团队可通过日常的自动检查,规范程序、美术成员的开发,从源头上对项目进行优化,规避风险,节约成本。
到官网下载SDK后,解压放在Editor,即可使用,它有很多类型的检测,每次检测扫描后会生成一份本地数据,需要使用上传工具上传数据到网站后台,然后登陆网站,可以查看分析报告。
详细使用请参考:https://blog.uwa4d.com/archives/UWA_Pipeline40.html
Unity UPR 静态资源检测
Unity UPR,https://upr.unity.cn 是Unity官方的专业团队,为企业用户提供真人真机测试、远程报告诊断、自动化集成以及私有云部署等定制化服务。这里主要介绍下它的静态资源检测
UPR 静态资源检测,不依赖 Unity Editor,通过无需安装的可执行程序,极快速的进行资源扫描。UPR 可以将扫描结果直观的展示出来,帮助开发者尽早发现资源文件中存在的问题。
下载工具后解压,使用assetcheck.exe命令行生成报告数据,可自行上传数据到网站查看报告,也可提前在网站建好项目,工具会自动上传。
版权归原作者 099_F11 所有, 如有侵权,请联系我们删除。