- Stats窗口
- Profiler窗口
- Memory Profiler
- 其他性能分析工具(Physica Debugger 窗口,Import Activity 窗口,Code Coverage 窗口,Profile Analyzer 窗口,IMGUI Debugger 窗口)
Stats 统级数据窗口
game窗口
可以初步查看游戏运行时,当前一帧的各项性能
- Audio表示音频的数据
- Level表示声音强度,单位是分贝,也就是dB。声音太大或太小都会影响玩家体验。
- DSP load表示数字信号处理器的负载。播放的声音越多、声音的采样率越高、声音效果越复杂,本变量的数值都会越大。应尽量避免这项数据过大。
- Clipping表示音频的裁剪情况。当音频信号超过设备支持的最大范围时,该音频信号会被裁剪。裁剪之后,该音频会出现一定程度失真的现象。应尽量避免这项数据过大。
- Stream load表示音频流的负载情况。音频的流式加载是指以持续的方式从音频源获取音频数据,而不是一次性加载全部数据。流式加载的主要优势是可以实时地处理和播放音频,无需等待全部数据加载完成。应尽量避免这项数据过大。
- FPS表示帧率,209.5FPS(4.8ms)表示平均每秒播放209.5张画面,平均每4.8毫秒播放一张画面。
- CPU的指标表示CPU处理一帧的时间。例如CPU:main 4.6ms render thread 0.5ms表示Unity的主线程处理这一帧所花费的时间是4.6毫秒,主线程主要负责游戏逻辑的更新,例如检测用户的输入、更新游戏对象的位置、碰撞检测等。在渲染线程处理这一帧所花费的时间是0.5毫秒,渲染线程负责显示游戏画面。
- Batches表示处理的绘制调用(Draw Call)批次的总数。 应尽量避免这项数据过大。
- Saved by batching表示有多少个绘制调用(Draw Call)被合并到了批次。应尽量让这项数据大。
- Tris表示当前摄像机视锥体的范围内三角面的个数。应尽量避免这项数据过大。
- Verts表示当前摄像机视锥体的范围内网格顶点的个数。 应尽量避免这项数据过大。
- 在3D建模软件中创建的模型导入到Unity后,该模型在Unity中显示的三角面和网格顶点的数量和在3D建模软件中的可能不同。因为3D建模软件和Unity对模型的三角面和网格顶点的计算方式可能是不一样的。
- Screen表示当前的屏幕分辨率,以及屏幕的内存占用量。例如Screen:1920×1080 - 23.7MB表示当前屏幕分辨率是1920×1080,屏幕占用了23.7MB的内存。 应尽量避免这项数据过大。
- SetPass calls表示在当前摄像机的渲染过程中,Unity切换着色器通道(Shader Pass)来渲染游戏对象的次数。一个着色器(Shader)可以包含多个着色器通道,每个着色器通道可以通过不同的方式来渲染游戏对象。但每次切换着色器通道都会消耗一定的性能。 应尽量避免这项数据过大。
- Shadow casters表示摄像机画面中有多少个游戏对象产生了阴影。同一个游戏对象产生较多的阴影,可能会被算作多个Shadow casters 应尽量避免这项数据过大。
- Visible skinned meshes表示当前摄像机中有多少个可见的蒙皮网格。应尽量避免这项数据过大。
- Animation components playing表示当前场景中有多少个Animation组件正在播放动画。播放动画会消耗性能。应尽量避免这项数据过大。没用的Animator组件和Animation组件可以考虑删掉。因为即使只有空的动画,Animator组件和Animation组件也会根据自己的工作流程进行每帧的计算和更新,以检查当前动画状态和过渡条件,这样就会消耗不必要的性能。
Draw Call 是什么?
要将游戏中的物体显示到屏幕上,就需要绘制它们。绘制之前,会先由CPU计算出它们的位置、
颜色等信息,然后发送绘制指令给GPU。GPU接受到CPU发过来的绘制指令,就会按照要求绘制东西在屏幕上。
Draw Call是指CPU向GPU发送绘制指令的过程,一个Draw Call就是CPU向GPU发送的一组绘制指令,可以绘制出一个或多个物体。
Draw Call有时也被简称为DC
Draw Call太多会使游戏变卡,优化的时候可以想办法降低Draw Call。
要降低Draw Call,可以使用合批技术,例如动态合批和静态合批。将多个Draw Call合批成一个批次(Batch),再由CPU发送给GPU,这样可以提升游戏性能。
垂直同步
垂直同步用于将游戏的帧率限制为显示器的刷新率,可以防止游戏画面在高速移动时的画面撕裂现象,使游戏画面更加平滑和连贯。
如果不启用垂直同步,当游戏的帧率高于显示器的刷新率时,图像的一部分可能会在显示器刷新之前更新,导致画面上出现明显的断裂线。而启用垂直同步后,图形处理器会等待显示器完成一次完整的刷新,然后再发送下一帧图像,确保每个图像帧都在刷新之前完全绘制,从而消除了撕裂现象。
但是启用垂直同步会消耗一些性能,也可能会出现卡顿的现象,要根据自己的实际情况来决定是否启用。
网格 蒙皮
网格用来定义一个模型的形状、大小和表面细节等信息,模型的所有顶点、线、面共同构成了这个模型的网格。蒙皮网格是一个与骨骼绑定的网格,这个网格可以发生形变和做出各种动作。一个网格 在没有蒙皮之前是不能发生形变的,也不能做出各种动作的。但是在成功蒙皮之后,这个网格就可以发生形变和做出各种动作。
Profiler 窗口
打开方式: Window——Analysis——Profiler
使用性能分析器进行分析时,其自身也是会消耗性能的。如果想获得更加准确的数据,可以使用独立性能分析器,即Profiler(Standalone Process)。
打开Profiler(Standalone Process)窗口的方法:
Window——Analysis——Profiler(Standalone Process)
独立性能分析器的运行不会影响收集的数据,因此可以获得更加准确的数据。它的用法和Profiler窗口相同,但是启动它的时间比打开Profiler窗口的时间长。
打开Profiler窗口后,运行Unity,再点击Profiler窗口上方的圆形按钮,就会开始收集当前开始的每一帧的性能,再点一下那个圆形按钮,则会停止收集,此时就可以双击右上部分的一个位置选中一帧,然后看这一帧的情况,一般我们可以选择波峰的一帧,这样容易看出性能开销大的原因。也可以推动时间轴,或者点击上方圆形按钮右侧的三个按钮,查看其它帧的情况。上方的Frame表示当前正在查看的帧数以及收集的总帧数,例如Frame:738/963表示一共收集了963帧,当前查看的是第738帧。
每一项左侧的颜色方块表示该项是显示的,如果点击颜色方块,则右侧会隐藏该项的数据。
如果不要显示某个模块的数据,可以点击左上角的“Profiler Modules”,取消勾选它,这样在性能分析器收集数据的时候,也不会收集这些数据,可以减少性能分析器的开销。如果要重新显示某个模块的数据,则勾选它即可。点击Restore Defaults会恢复默认的设置。点击小齿轮,再点击Add,可以自定义一个新的模块,并自定义这个模块要分析的性能,且可以在上方的输入框处改名,然后点击Save Changes可以保存。如果要删除它,则点击Delete Module即可删除它,同样,点击Save Changes可以保存。
如果要清除当前收集的所有帧的数据,则可以点击上方的“Clear”。再次点击Profiler窗口上方的圆形按钮,就会开始收集当前开始的每一帧的性能,再点一下那个圆形按钮,则会停止收集,此时就可以双击右上部分的一个位置选中一帧,然后看这一帧的情况。
选中一帧后,除了可以在右侧看到这一帧的情况,还可以在下方看到这一帧更加具体的情况。
要找出造成性能开销的因素,可以尝试禁用场景中的游戏对象。如果禁用后,看到性能提升了,则说明问题出在这个游戏对象身上,优化的时候就可以从它身上下手。
点击圆形按钮左侧的下拉菜单,可以选择分析什么的性能。如果选择Play Mode,则会分析游戏在运行时的性能,如果选择Edit Mode,则会分析编辑器模式下游戏的性能。
如果用手机的数据线成功连接到电脑,在手机上运行Unity的游戏,这里会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
也可以让手机和电脑都连接同一个wifi,这样一来,这里也会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
注意,无论是用wifi还是数据线,构建项目时必须在Build Settings窗口中勾选Development Build和Autoconnect Profiler。
选择上方的Clear on Play,则在每次重新运行游戏的时候,都会清空收集的数据,以便我们重新开始收集这一次的数据。
如果要保存收集到的数据到本地,方便之后查看,可以点击右上方的图标来保存。右上方也有一个图标可以读取之前保存的数据。
选择上方的Deep Profile,然后重新启动性能分析器,则性能分析器收集数据的时候,会把所有C#代码中的方法的信息也收集过来。例如我们自己写的C#脚本,里面的方法只要被调用了,就会被收集过来,方便我们从性能分析器查看它们的性能。在Profiler窗口选择CPU Usage模块,选中一帧,然后在下面选择Hierarchy,右侧选择Main Thread,再在右侧的搜索栏处搜索该方法的名字,就可以找到它,并查看它的性能。
注意,使用Deep Profile会耗费较大的性能,可能会导致性能分析器的运行变慢。小项目这样做是可以的,但是如果项目较大,这样做可能会导致性能分析器运行过慢。如果要分析某一段代码的性能,可以使用Profiler.BeginSample方法和Profiler.EndSample方法。
选中Deep Profile右侧的Call Stacks按钮,这样在收集性能数据的时候,每一帧都会记录该方法的的调用栈信息。GC.Alloc、UnsafeUtility.Malloc、JobHandle.Complete是Unity的方法,启用Call Stacks且勾选它们后,如果Unity有调用它们,则可以在Hierarchy或Raw Hierarchy右侧的搜索框中搜索到它们,这样就可以查看它们的性能了。
GC.Alloc表示GC的内存分配情况。
UnsafeUtility.Malloc(Persistent)用于在内存中分配指定大小的未初始化内存块。这个方法会直接在堆上分配内存,并可以绕过自动内存管理功能,需要手动管理内存的生命周期和释放。一般情况下,只有在处理非托管内存的特定场景下才会使用UnsafeUtility.Malloc方法。
JobHandle.Complete表示Job的完成情况。这里的Job是指Unity的Job System的一组特定的任务。
点击右上角的三点,有一些选项可以选择。
Color Blind Mode表示色盲模式,开启后会调整Profile窗口的颜色,照顾色盲用户。
Show Stats for 'current frame'开启后,当点击Frame:XXX/XXX左侧的按钮,从而选中最后一帧,则会显示最后一帧的统计信息。
Preferences,点击后会打开Project Settings窗口,用于设置性能分析器的一些属性。
Frame Count,开始收集性能的数据时,每次最多可以查看多少帧。例如数值是300,则表示最多可以查看300帧。
Show Stats for 'current frame',勾选后,则在右上角的三点会出现Show Stats for 'current frame'供我们选择。
Default recording state,选择Enable,则重启Unity再打开Profiler窗口,如果此时的模式是Edit Mode,则会自动开始点击圆形按钮,开始收集数据。选择Disabled,则重启Unity再打开Profiler窗口,需要手动点击圆形按钮,才会开始收集数据。选择Remember,则会按照当前圆形按钮是启用还是禁用来决定下一次重启Unity再打开Profiler窗口时,该圆形按钮是否启用。
Default editor target mode on start,选择Play Mode,则重启Unity再打开Profiler窗口,左上方会选择Play Mode,即在播放模式下才会收集数据。如果选择Edit Mode,则重启Unity再打开Profiler窗口,左上方会选择Edit Mode,即在编辑器模式下收集数据。
Custom connection ID,当有多个Unity项目的实例同时运行,它们都要使用性能分析器来分析性能,则可以通过这个Custom connection ID来区分它们。
CPU Usage模块:
下方窗口可以选择Timeline、Hierarchy、Raw Hierarchy。
选择Timeline,可以通过时间轴的方式查看这一帧中CPU依次干了什么。
选择Hierarchy,可以查看CPU在这一帧中做的事情所消耗的性能和所花费的时间。Total表示一共占用了CPU使用情况的百分之几。Self表示自身的代码占用了CPU使用情况的百分之几,调用其它方法的代码不算在内的。Calls表示被调用了几次。GC Alloc表示GC分配的内存,当一个对象被释放后,它GC分配的内存不会马上被回收,所有GC分配的内存的总量达到一定程度,会触发GC,此时垃圾回收器才会把这些内存回收,不过同时也会造成游戏卡一下。Time ms表示一共耗时多少毫秒。Self ms表示表示自身的代码耗时多少毫秒,调用其它方法的代码不算在内的。
选择Raw Hierarchy比起Hierarchy会单独列出更多信息,Hierarchy实际上是把这些信息合并了。
调用栈(Call Stack)
是计算机程序在执行过程中记录函数调用的一种数据结构。
调用栈是一个栈结构,即先进后出。它用于记录程序执行过程中,每个函数被调用的情况。
当一个函数被调用时,它的相关信息,如函数名、参数、返回地址等,会被添加进调用栈中。当该函数执行完成后,相应的信息会从调用栈中移除。通过不断添加和移除函数调用的信息,调用栈就记录了程序执行的顺序。
调用栈对于程序调试和分析非常有用。当程序出现错误或异常时,可以通过查看调用栈来确定错误发生的位置和函数调用的顺序。调试器通常会显示当前调用栈的信息,以帮助开发人员查看函数的执行过程并找出发生异常的原因。
托管内存与非托管内存
托管内存是由垃圾回收器自动管理的内存,当达到一定量时,会由垃圾回收器自动释放它们。
托管内存存放在托管堆中。托管堆是一种用于存储和管理托管对象的内存区域。每当创建一个新的托管对象时,托管堆就会分配内存空间给这个对象,并记录这个对象的信息。当托管对象不再被引用,垃圾回收器会自动将其标记为垃圾,并在适当的时候回收其占用的内存空间。
非托管内存不会自动被回收,它们需要我们程序员写代码去管理和释放它们。
非托管内存并不固定存储在一个地方,它们往往分散存储在不同的地方,例如操作系统的内存、临时缓冲区等。
DOTS(Data-Oriented Technology Stack)
是Unity引擎中的一个新的编程模型和工具集。它旨在提供更高性能、更可扩展和更并行化的游戏开发体验。
- ECS框架:ECS是一种用于组织和管理游戏对象的方式。它将游戏对象分解为实体(Entity)、组件(Component)和系统(System)。这种模式更加适合于并行处理和优化,可以提高游戏性能。
- Job System(作业系统):Job System允许开发者将任务并行化,利用多核处理器的能力。它通过将任务划分为小的作业(jobs)并在多个线程上并发执行来提高性能。Job System还可以与ECS结合使用,使得开发者可以更好地控制游戏的行为。
- Burst Compiler(突发编译器):Burst Compiler是一种高性能的C#编译器,可以将C#代码转换为高效的本机代码,以进一步提高游戏的性能。
DOTS的目标是为游戏开发者提供更好的性能和可扩展性,并更好地利用现代硬件的并行能力。它适用于需要处理大量实体和需要高性能的游戏项目。
Frame Debugger窗口
也叫帧调试器窗口,用于查看每一帧的画面是如何渲染出来的,可以详细查看这一帧的绘制过程。
打开Frame Debugger面板的方式:
Window——Analysis——Frame Debugger
按下“Enable”,则会启动帧调试,此时如果运行了游戏,则会自动暂停,然后当前这帧的渲染情况可以在这个窗口中查看。
上方的 X of X 表示绘制过程中有多少步,可以查看下一步或上一步。
如果要禁用帧调试,可以按下“Disable”。
用Frame Debugger窗口查看当前一帧的每一步时,可以配合Stats窗口使用,以此来确定哪一个物体造成的性能开销较大。
绘制的步骤越少,性能越好。
Frame Debugger窗口也能看到每一帧的Shader信息,但是需要有一定Shader基础才能看懂。
大多数平台都支持帧调试器的使用,可以用手机的数据线成功连接到电脑,在手机上运行Unity的游戏,Frame Debugger窗口中会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
也可以让手机和电脑都连接同一个wifi,这样一来,Frame Debugger窗口中也会多出该手机设备供我们选择,我们就可以分析该手机设备上运行的Unity项目的性能。
但是要注意,构建时必须在Project Settings窗口中勾选“Development Build”。而且有些平台可能不支持Frame Debugger的使用,例如WebGL平台。
参考:siki学院性能优化课程,挂不了链接,会被识别为广告