Unity 性能优化记录(一)性能分析工具的使用

最近在研究Unity性能优化相关的内容,接触了几个Unity官方自己的工具,这里总结一下它们的使用方式以及如何结合着使用。

我主要用到了以下几个工具:

  • UPR(Unity Performance Report)
  • Profiler
  • Memory Profiler

首先总体上讲一下这三者之间的关系:Profiler是Unity Editor中自带的性能分析工具,不需要额外下载,能对CPU,GPU,内存,Render,物理,网络等等的性能数据进行搜集。而UPR则是利用了Profiler的数据进行了进一步的专业分析和统计,Memory Profiler是针对Profiler的内存数据进行了专门的分析,在运行期间可以进行内存的快照收集。

这里有两点需要注意:

  • 最好将Unity打包到对应的平台上(打包时记得勾选Development Build),运行然后通过数据线或者wifi的方式把性能数据传输回来。Editor中会有很多干扰数据并没有用处。
  • 这三者的性能数据来源都是Development Build模式下的游戏自身,所以可能会有冲突,最起码UPR和Profiler不可以同时使用,所以UPR官方的文档也说了不能勾选Autoconnect Profiler

工具简介

这里简单介绍下这几个工具能做什么以及擅长做什么。

Profiler

首先介绍的是Profiler,这个工具是Unity自带的,在Editor里面打开就有,他的功能是很全面的,包含了CPU耗时分析,GPU耗时分析,内存分配等等,具体的我就不细说了,官方文档很详细,我就不摘抄了。

需要注意的一点可能就是CPU分析工具,这个功能我认为是Profiler比其他两个工具更为擅长的,或者说更为详细的.

我简单截了个图看一下:

我们只要关注途中绿色方框内的东西:

  • 最大的绿色方框就是CPU实时的运行图,横坐标为运行时的每一帧,纵坐标为该帧的总耗时,如果该帧的耗时是33ms,那就代表是30FPS,因为我的项目是锁帧在30的,所以我的耗时在33ms上下波动。
  • 最上方的小框内有两个按钮,一个是Deep Profile,开启该选项后会有一些更加详细的性能数据,但是问题就是,你可能会发现自己的游戏运行变的卡顿了起来,所以除非你要定位某个具体的性能点了,不要开启,影响观察。另一个按钮是Call stack,开启之后会记录每一帧中的每个函数的调用栈,下拉按钮中展示了收集那些函数的调用栈,默认勾选的是GC.Alloc,注意这个指标的意思不是回收了多少垃圾,而是函数申请了多少内存
  • 左边的Timeline那里可以选择三种不同的模式,非别是Timeline,Hierarchy, Raw Hierarchy, Timeline展示的就是每个函数的时间线,但是如果你想看每个函数的具体耗时,可以选择Hierarchy,如果发现了哪个函数有问题,可以选择右边的Calls

注意,calls面板右边一个callTo,一个callFrom里面的列表并不是调用栈,而是那个函数调用了本函数,也就是说,callFrom里面的每个函数都调用了你选择的那个函数

其他的内容大家可以自己去看看官方文档了,没有什么特别好注意的了。

Memory Profiler

这个工具没啥特别好说的,功能很简单,所以很直观,就是你可以随之对内存进行快照,看看快照中每一种资源的占比,具体是哪个资源占用了内存。

UPR

UPR其实在Profiler的基础上,如果没有安装UPR Package没有多收集什么数据,但是会把数据进行汇总以一个更加直观的方式,他会直接帮你把CPU占比高的函数用图的方式直接展示,会对某些超过了正常的指标会标红,而且最重要的是,他不像Profiler一样只能看最近那些帧的数据。

所以如果有了UPR,大部分情况下用不到Profiler了。

使用方式

Profiler和Memory Profiler

这个很简单,Development Build模式下打包完后,数据线连接或者wifi连接都可以

具体可以看文档:https://docs.unity3d.com/Manual/profiler-profiling-applications.html

暂时没有踩坑

UPR

接下来到了我们的重头戏,Unity Performance Report了,该工具的使用有很多配套的工具,有UPR App,UPR Desktop,UPR Package, AssetChecker。

我们要使用UPR,首先要去网站上创建一个项目,在项目中填写我们的Unity Package Name,Unity版本等,其中这个Package Name是最重要的。

然后我们就可以在项目下创建测试,创建测试的时候有很多选项可以选择,高级选项中可以配置你是否锁帧等参数,注意如果开了“开启内存分配调用栈”,会让游戏变卡,但是你就可以在报告里看到你关注的那些开销高的方法的调用栈了。

然后我们就可以进行打包测试了。

我们想要使用UPR,首先需要在打包时勾选Development Build,并且不能勾选Autoconnect Profiler,然后就是正常的打包流程。

打包到设备上的步骤完成以后,我们想要将性能数据上传UPR网站分析,就需要用到UPR的工具了。

一开始说的工具中,UPR App和UPR Desktop是二选一,必须选一个才可以。

UPR APP装在手机上的。我们在UPR的网站上创建了一个测试,会生成一个二维码和sessionid,用UPR App扫描二维码,会获取我们创建测试所属项目的包名,然后这个时候我们去运行,UPR App就会帮我们启动游戏,至于启动后的操作就不赘述,只是说记不住,但是用一下就明白

而笔者采用的是Mac系统下,使用UPR Desktop来测试安装在Android下的设备,因为这样可以使用UPR Package(一个unitypakcage,import到项目中就可以了)加ADB的方式获取更为详细的数据,比如电量和温度等

整体的安装和使用方式可以参考官网,但是有几点踩过坑的地方:

  • Mac要使用UPR需要先安装.Net3.0
  • Mac使用UPR是通过命令行的方式,在使用前需要先运行两个命令
    • sudo chmod +x UnityPerfProfiler
    • sudo spctl --master-disable
  • 如果不通过adb方式,那么直接运行./UnityPerfProfiler -p <device_ip> -s <session_id>就好,这个东西不需要PackageName是对的,但是如果你要通过adb方式连接,并且按照官网设置的了adb的三个forward规则,还是出现下面的报错:那么你就要看一下是不是你的packageName写错了,或者项目的Player Settings里面覆盖到了android的pacakgename,Unity的package name不仅可以在最上面配置一个默认的,还可以针对每个平台配置覆盖的packagename

混合使用总结

个人一套下来,认为应该比较流畅的方式是:

  • 先上UPR,可以很直观的看到哪里有性能瓶颈
  • 定位到了CPU哪个函数有瓶颈,结合本地观察Profiler的CPU Timeline或Hierachy。
  • 定位到了内存有问题,比如泄漏或者过大的问题,结合本地的Memroy Profiler看看那一部分内存较大,具体是什么占用了内存,是否能优化等。