Unity 优化篇| 优化的基本概念/意义,Unity Profiler工具的使用 以及 性能分析的方法精华收藏
Posted 呆呆敲代码的小Y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 优化篇| 优化的基本概念/意义,Unity Profiler工具的使用 以及 性能分析的方法精华收藏相关的知识,希望对你有一定的参考价值。
🎬 博客主页:https://xiaoy.blog.csdn.net
🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉
🎄 学习专栏推荐:👑Unity系统学习专栏👑
🌲 游戏制作专栏推荐:👑游戏制作👑
🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📆 未来很长,值得我们全力奔赴更美好的生活✨
------------------❤️分割线❤️-------------------------
📢前言
- 谈及
优化
,作为一个程序员来说,应该都知道是怎么一回事。 - 程序优化是指对解决同一问题的几个不同的程序,进行比较、修改、调整或重新编写程序
- 把一般程序变换为语句最少、占用内存量少、处理速度最快、外部设备分时使用效率最高的最优程序
- 我觉得
优化
和性价比
其实很像。 - 我们在生活中使用最少的钱去买最实用的物品是性价比最高的。
- 同理,如何让程序在最省性能的情况下去完美执行同一个功能 就可以理解成 优化。
那本篇文章就来简单讲一讲Unity中 优化 的概念。
🎬Unity 中的 优化
一般来说,要实现某个功能,我们可以有N种做法,就跟一个数学题有很多种题解一样。
我们要做的 就是以一种 最优解
的方式用编程做出这道题!
Unity中的优化有很多个方面,包括但不限于:
脚本代码优化策略、UI常规优化逻辑、物理引擎优化、内存管理优化、艺术类资源优化、批处理 和 图形渲染优化 等
优化前需要问自己的几个问题:为什么要优化 、优化的目标是什么、哪些部分才需要优化、能够接受由此带来的可能的资源消耗(人力、维护、空间等)吗?
所以在进行相关的优化操作之前,我们首先要学会 性能分析。
🎥Unity性能分析工具
在Unity中有一款自带的性能分析工具 Unity Profiler
我们可以从菜单栏打开查看 Window -> Profiler
也可以按快捷键 Ctrl +7 打开
使用这个工具可以让我们在程序运行时,实时便捷的观察一些性能所需要的数据。
Unity Profiler内置在Unity编辑器中,在程序运行的时候可以为大量的Unity3D子系统生成使用情况和统计报告
这可以缩小我们为性能瓶颈的搜索范围提供很大的帮助。
Profiler 可以收集的数据如下:
- CPU消耗量(每个主要子系统)
- 基本和详细的渲染和GPU信息
- 运行时内存分配和总消耗量
- 音频源/数据的使用情况
- 物理引擎(2D和3D)的使用情况
- 网络信息传递和活动情况
- 视频回放的使用情况
- 基本和详细的用户界面性能
- 全局光照统计数据
通常有两种使用Profiler工具的方法:指令注入 和 基准分析
指令注入:
- 通过观察目标函数调用的行为,分配了多少内存,来观察应用程序的内部工作情况,这通常会得到当前执行情况的精准图像,并可能找到问题的根源。
但是,这通常不是一种发现性能问题的高效方法,因为任何的应用程序的性能分析都会代码额外的性能损耗!
基准分析:
- 我们在分析应用程序中的具体每行代码之前,应该要对应用程序进行一次系统全面的实际体验。
- 最好是在应用运行的期间收集一些基本的数据,也可以理解成测试。
- 这个测试用例可以是 简单对应用的玩法试玩几秒、不同场景的切换等。
- 该操作的主要意义是让我们体验到一个大致的感觉,在性能明显变差的时候能够及时关注重点,在进一步分析。
我们在进行基准分析的时候通常会对渲染帧率(FPS)、总体内存消耗、CPU活动 和 CPU/GPU温度比较感兴趣。
这些指标的手机方式都相对简单,可以作为性能分析的首先方式。
在进行基本分析之后在进行指令注入才是最好的分析方式。
但是如果想得到真实的数据样本,则应该在实际的平台上测试进行基准分析。
我们不应该通过在Editor上获取的数据作为真正的游戏数据去处理。
因为在Editor上可能会有一个额外的性能开销 或者 隐藏某些在真实应用程序中潜在的竞争条件。
有时候在Editor进行分析的时候会比实际应用程序快的多
这是因为在进行序列化数据(音频、预制体)的时候编辑器早就已经缓存过了,所以能比实际应用程序更快的访问这些数据
所以我们应该将性能分析工具挂载到实际的应用程序中以获取真实的数据样本!
通过在Profiler窗口的Connected Player
选项,可以选择分析基于Editor的实例(通过在Editor的Play模式运行) 还是独立的实例(在编辑器外独立构建并运行)
不同版本的Unity,这个选项的位置和名称可能有所不同,不过都在这一块的菜单栏里,仔细找一下就好。
下面来说一下不同的平台连接 Unity Profiler
的方法。
📒不同的平台连接 Unity Profiler 的方法。
1️⃣1.连接到android设备
连接到Android设备的方法有两种,分别是通过WiFi连接 和 通过ADB工具连接。
第一种:通过WiFi连接到Android设备的方法:
- 确保当前构建应用程序时启用了Development Build 和Autoconnect Profiler标志
- 将Android 和 电脑 连接到本地WiFi网络
- 通过USB数据线将Android连接到电脑
- 同之前一样通过Build & Run 选项构建应用程序
- 在Unity编辑器中打开Profiler,在Connected Player 下选择设备
接下来等待一会之后,应用构建应用程序并通过USB连接推送到Android设备,而Profiler会通过WiFi对Android设备进行连接。
之后就可以看到Profiler窗口正在收集Android设备的分析数据(真是的数据样本)。
第二种:使用ADB工具连接:
- 确保自己的电脑安装了Unity所需的Android SDK/NDK,没有的 可以去下载安装
- 通过USB数据线将Android连接到电脑
- 确保当前构建应用程序时启用了Development Build 和Autoconnect Profiler标志
- 同之前一样通过Build & Run 选项构建应用程序
- 在Unity编辑器中打开Profiler,并在Connencted Player 下选择设备
然后就可以看到Profiler窗口正在收集Android设备的分析数据。
2️⃣2.连接到ios设备
Profiler也可以连接到运行在iOS设备上的应用实例,可以通过共享WiFi来实现。
不过,还是仅仅当Unity运行在Apple Mac设备上时,才能通过远程连接到 ios 设备上才可行!
- 确保当前构建应用程序时启用了Development Build 和Autoconnect Profiler标志
- 将iOS和Mac设备连接到本地WiFi网络,或者连接到专用的WiFi网络
- 通过USB数据线将iOS连接到Mac上
- 同之前一样通过Build & Run 选项构建应用程序
- 在Unity编辑器中打开Profiler,并在Connencted Player 下选择设备
然后就可以通过Profiler窗口来收集iOS设备上的数据并分析了!
3️⃣3.连接到WebGLS实例
Profiler可以连接到Unity WebGL实例。
为此,可以在构建WebGL应用程序并从编辑器中运行它时,确保当前构建应用程序时启用了Development Build 和Autoconnect Profiler标志。
应用程序会通过操作系统默认的浏览器运行,我们也可以通过不停的更改默认浏览器来达到应用程序在不同浏览器中的表现结果。
但是Profiler 连接只能在应用程序首次从Editor中启动时建立。
之前的Profiler不能连接到已经在浏览器中运行的独立WebGL实例上。
这限制了基准分析WebGL的准确性,因为他有Editor上的一些额外开销。
📒Profiler窗口解析
接下来介绍一下Profile窗口的一些基本特性,
由于不同版本的Unity这个窗口都会略微有些不同所以本篇文章中使用的是Unity2019版本
后续没什么大问题的话也都是基于这个版本做的教程介绍,不过问题不大,不同版本核心功能都没太大的变化。
这是Unity2019的Profiler窗口视图,暂且分为四个部分进行介绍。
- Profiler控件
- 时间轴视图
- 细分视图控件栏
- 细分视图
1️⃣1.Profiler控件
顶部的选项栏包括多个下拉和开关按钮,他们可决定要分析什么数据,以及在每个子系统手机数据的深度。
Profiler Modules
默认情况下,Profiler将会对加几个不同的子系统收集数据,这些子系统覆盖了Unity引擎在时间轴视图中的大部分子系统。
这些子系统被组织成包含相关数据的各个区域,可以通过Profiler Modules来 添加 或者 移除 额外的区域。
有些Unity的版本也被叫做:Add Profiler
Playmode
Playmode
下拉框提供了许多选项,从中可以选择要分析的目标Unity实例。
可以是当前的编辑器应用程序,也可以是本地独立运行的应用程序实例,或者远程设备上的应用程序实例。
Frame
显示所在帧数/总帧数。
Clear
Clear按钮清除时间轴视图中所有的分析数据。
Clear on Play
播放时清除,跟Clear作用一致
Deep Profile
深度分析。普通的分析只记录常见的Unity回调方法(如Awake()、Start()、Update())所但会的时间和内存分配信息。
启用Deep Profile 选项可以用更深层次的指令重新编译脚本,允许它统计每个调用的方法。
这往往会导致运行时的指令注入成本比正常情况下药大得多,并使用大量的内存,因为在运行时收集的是整个调用堆栈的数据。
所以说这个选项一般不会开启,当默认的分析选项无法提供足够的详情以指出问题根源时,最好保留这个选项!
Call Stacks
调用堆栈。设置这个可以在模块详细信息或者timeline视图观察GC的完整堆栈
Load
读取先前保存的数据,在按下shift按钮时单击“Load”,则文件内容将附加到内存中的当前配置文件帧。
Save
将录制的帧写入文件,以(.data)为后缀名。
Save按钮将当前显示在时间轴视图上的所有Profiler数据保存到文件中。
这种方法一次只能保存300帧数据,要保存更多的数据,需要手动创建新文件。
2️⃣2.时间轴视图
时间轴视图
就是现实运行期间收集的分析数据,将其组织到一系列区域中。
每个区域关注Unity中不同的子系统分析的数据,每个区域都有两部分。
右边是分析数据的图形展示,左边是一系列用于 启用/禁用 不同 行为/数据类型 的复选框。
这些复选框可以切换,以改变图形部分内对应数据类型的可见性。
我们可以在任何时刻惦记时间轴的图形部分视图,查看给定帧的更多信息。
3️⃣3.细分视图控件栏
根据时间轴上选定的区域,细分视图控件栏内将显示不同 的下拉框和切换按钮选项。
不同区域提供不同的控件,这些选项声明了什么信息是可见的 以及如何呈现在细分视图上。
4️⃣4.细分视图
根据当前选择的区域以及细分视图控件栏中选择的选项,细分视图中显示的信息会有很大的不同。
接下来就来介绍下每个区域以及细分视图中可用的不同类型的信息和选项。
CPU使用情况 区域
这个区域显示CPU所有使用情况和统计数据。
包括Unity大量的子系统,比如 MonoBehaviour组件、摄像机、一些渲染和物理处理、用户界面、音频处理、Profiler等。
在细分视图中,显示CPU使用情况数据有3种不同的模式:
- Hierarchy 模式
- Raw Hierarchy 模式
- Timeline 模式
Hierarchy 模式显示大部分调用栈的调用,还会合并类似的数据元素和Unity的全局函数调用。
Raw Hierarchy 模式 和 Hierarchy 模式很相似,但是前者会将全局Unity函数调用隔离到单独的条目中,而不是合并到一个大条目中。
Timeline 模式将细分视图垂直组织到不同的部分,代表运行时的不同线程。
例如主线程、渲染线程和各种后台工作线程,成为Unity Job System,用于加载诸如场景和其他资源等活动。
Timeline 模式提供了一种非常清晰的方式,以明确调用栈中的哪个方法消耗的时间最多,以及处理时间如何与同一帧中调用的其他方法进行比较。
通常 CPU使用情况区域
对于检测问题最有效果。
GPU使用情况 区域
GPU使用情况 区域
和 CPU使用情况 区域类似,但前者展示的是发生在GPU上的方法调用和处理时间。
这个区域中的相关Unity方法调用与摄像机、绘制、不同名的和透明的几何图形、光照和阴影等有关。
GPU使用情况 区域提供了类似 CPU使用情况 区域的层级信息,并估计调用各种渲染函数所花费的时间。
渲染 区域
渲染 区域
提供了一些常用的渲染统计数据。
细分视图 中提供了有用的信息,诸如SetPass调用的数量(Draw Call)、渲染到场景的批次总数、通过动态批处理和静态批处理节省的批次数量和他们的生成方式,以及纹理的内存消耗。
内存区域
内存区域允许在细分视图时以两种模式检视应用程序的内存使用情况:
- Simple 模式
- Detailed 模式
Simple 模式只提供子系统内存消耗的高层次概览。
包括Unity底层引擎、Mono框架(由垃圾回收管理的整个堆的大小)、图形资源、音频资源、缓冲区 和 保存Profile收集的数据的内存。
Detailed 模式显示每个GameObject和MonoBehaviours为其Native和Managed表示所消耗的内存。
音频区域
音频区域是音频统计数据的预览,他也可以用于估量音频系统的CPU消耗,以及音频和音频剪辑的总内存消耗。
细分视图中可以洞悉音频系统的运行方式,以及各种音频通道和组的用法。
Physics 3D 和 Physics 2D 区域
物理区域有两个,一个是3D物理,另一个则是2D物理。
这个区域提供不同的物理统计数据,例如Rigidbody、Collider和Contact技术。
网络信息 和 网络操作 区域
这两个区域提供了Unity网络系统的信息,所显示的信息取决于应用程序是否使用Unity提供的高级API(HLAPI)或传输层API(TLAPI)。
HLAPI是一个更易用的系统,用于管理Player和GameObject自动网络同步
而TLAPI知识套接字层级上操作的一个博层,它允许Unity开发者构建自己的网络系统。
视频区域
如果应用程序使用Unity的VideoPlayer API,那么这个区域对于分析视频回放行为很有效果。
UI 和 UI详情 区域
这些区域用于洞察使用Unity内建UI系统的应用程序。
如果使用的是NGUI或者其他第三方的UI系统,那这个区域则无关紧要了。
优化差的UI通常会影响CPU或GPU,因为UI是我们工程首先要面对的第一个子系统。
在很多项目里面UI占得比重还是很大的,所以UI优化也是一个很重要的点,后面会详细介绍。
全局光照区域
全局光照区域为Unity的全局光照系统提供了大量的优秀细节。
如果应用程序使用GI,就应该参考这个区域,已验证应用程序是否正常执行。
👑性能分析的方法
上面说了Unity中的性能分析工具Profiler,那就再来说一下进行性能分析的最佳方法。
因为我们在项目中很难的去直接找到需要优化的某个地方,所以就要合理的进行性能分析以得到最佳的结果。
所以说一份合理的任务清单可以让我们可以更高效率的去检查出相关问题。
下面是参考 《Unity游戏优化第2版》 这本书中总结的一些适用于绝大多数Unity项目的几个方法:
- 验证目标脚本是否出现在场景中
- 验证脚本在场景中出现的次数是否正确
- 验证事件的正确顺序
- 最小化正在进行的代码更改
- 尽量减少内部干扰
- 尽量减少外部干扰
下面来简单介绍一下这几个方法,方便我们进行排查的时候使用。
🏳️🌈验证目标脚本是否出现在场景中
这种情况适用于我们期待看到某种效果,但是这种效果却没有看到的时候。
出现上面这种情况就很大可能是脚本未出现在场景中,所以我们需要手动排查一下。
可以在 Hierarchy窗口 的文本框中输入以下内容:
t:<script name>
这样就可以快速检索场景中挂载该脚本的GameObject游戏对象。
如果未检测到我们的脚本,那么很大可能就是未将脚本挂载到场景中。
当然也要注意游戏对象的激活状态,如果游戏对象是处于非激活状态的话,脚本还是没法正常运行的!
🏳️🌈验证脚本在场景中出现的次数是否正确
如果在 Profiler 查看数据时,观测到某个 MonoBehaviour 方法执行的次数比预期的多。
或者执行的时间比预期的长,就可能需要再次检查他在场景中出现的次数是否与预期的一样多。
同理,如果场景中期望出现的特定数量的组件,但是在段列表中显示的组件数比这更多(或更少)。
那么就需要我们去检查一下了,最好是编写一些 初始化代码 来防止这种情况再次发生。
🏳️🌈验证事件的正确顺序
Unity 应用主要执行从本地代码到托管代码的一系列回调。
例如我们都知道的 Awake()、Start()、Update() 等,都是最常用的一些回调方法。
但是有时候我们脚本有很多,我们在某个脚本的 Awake() 中定义了一些东西,做了一些功能。
在另一个脚本中的 Awake() 方法中调用了上面那个 Awake() 中定义的某些东西,这样就会出现一些未知的变化。
原因是我们不能对调用的相同类型事件的顺序进行细粒度控制,所以有时候就会出现事件顺序的问题从而导致项目出现问题。
我们可以在前期尽可能的使用 Awake() 方法来执行某些初始化的方法,在程序运行第一帧就执行。
后期处理的时候就可以在MonoBehaviour组件的 Start() 回调中进行,因为他总是在所有的 Awake() 执行之后,第一个 Update() 之前被调用。
同理,后期更新的时候也可以使用 LateUpdate() 来进行,某些特定情况下除外。
如果很难确定某些事件的执行顺序就使用 Debug.Log() 打印的方式去选择。
🏳️🌈最小化正在进行的代码更改
为了查找性能问题在项目中进行代码更改最好谨慎的进行,因为随着时间的推移,我们进行的更改很容易忘记。
尤其是我们在项目中添加的一些调试日志等等,后期都要记得及时删除哦。
因为Unity的调试控制台窗口日志记录在CPU和内存中都很昂贵,会消耗一些不必要的运行开销。
🏳️🌈尽量减少内部干扰
这里说的 内部干扰,是指Unity引擎的干扰,比如某些功能设置,垂直同步等等。
🏳️🌈尽量减少外部干扰
外部干扰 则是指在运行我们的应用程序时,设备有没有在后台运行其他的非常消耗CPU周期或者占用大量内存的程序。
从而导致可用内存不足干扰测试,因为它会导致更多的缓存丢失。
如果运行效果比预期效果要差很多,则需要仔细检查系统后台有没有进行其它的十分消耗性能的程序。
💬总结
- 本文整理了 Unity中的优化概念 和 Profiler工具的使用方法 以及 性能分析方法。
- 也是将本篇文章作为【Unity优化篇】专栏的第一篇。
- 为以后的 Unity性能优化文章做一个开头,写的内容还是很丰富的。
- 后面也会输出更多的系列学习文章,希望大家多多捧场呀!
🚀往期优质文章分享
- ❤️Unity零基础到入门 | 游戏引擎 Unity 从0到1的 系统学习 路线【全面总结-建议收藏】!
- 🧡花一天时间做一个高质量飞机大战游戏,过万字Unity完整教程!漂亮学妹看了直呼666!
- 💛通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难
- 💚重回童年的经典系列☀️|【贪吃蛇小游戏】近两万字完整制作过程+解析+源码 【建议收藏学习】
- 🤍重回童年的经典系列☀️| 【皇室战争 】 的 即时战斗类 复刻游戏Demo!两万多字游戏制作过程+解析!
- 💙重回童年的经典系列☀️| 【横版街机格斗游戏】类似“恐龙快打” 该如何制作? | 一起来学习 顺便送源码【建议收藏学习】
- 💜重回童年的经典系列☀️|【炸弹人小游戏】制作过程+解析 | 收藏起来跟曾经的小伙伴一起梦回童年!
🚀 优质专栏分享 🚀 |
- 🎄如果感觉文章看完了不过瘾,可以来我的其他 专栏 看一下哦~
- 🎄比如以下几个专栏:Unity基础知识学习专栏、Unity游戏制作专栏、Unity实战类项目 和 算法学习专栏
- 🎄可以学习更多的关于Unity引擎的相关内容哦!直接点击下面颜色字体就可以跳转啦!
【游戏开发爱好者社区】活动进行中,每周打卡送书籍等礼品,期待你的加入
🚀 社区活动,重磅来袭 🚀 |
【游戏开发爱好者社区】在本周重磅新推出【每日打卡】活动
🎁 新玩法,奖励升级!游戏开发爱好者社区:https://bbs.csdn.net/forums/unitygame
社区中心思想:今天你学到了什么?
在社区你可以做些什么: 每日强化知识点,白嫖书籍礼品!
一个人可以走的很快,一群人才能走的更远!🔥爆C站的游戏开发爱好者社区欢迎您的加入!
更多白嫖活动详情:https://bbs.csdn.net/forums/unitygame?typeId=19603
温馨提示: 点击下面卡片可以获取更多编程知识,包括各种语言学习资料,上千套PPT模板和各种游戏源码素材等等资料。更多内容可自行查看哦!
以上是关于Unity 优化篇| 优化的基本概念/意义,Unity Profiler工具的使用 以及 性能分析的方法精华收藏的主要内容,如果未能解决你的问题,请参考以下文章
Unity 优化篇 | 优化专栏《导航帖》,全面学习Unity优化技巧,让我们的Unity技术上升一个档次
Unity 优化篇 | 优化专栏《导航帖》,全面学习Unity优化技巧,让我们的Unity技术上升一个档次