关注“之家技术”,获取更多技术干货
总篇175篇 2022年第50篇
背景
Unity 优化涵盖范围大,涉及知识面广,随着功能不断增长,需要优化的内容也在增多。在VI销冠神器的几次迭代中发现项目的各项性能指标都存在偏差,所以开始着手进行项目的优化工作。
本篇文章以浅显易懂的角度介绍一下 Unity 优化和VI销冠神器的优化经验。
1.渲染流程
本节主要是为不熟悉画面渲染的读者讲解一下渲染的流程,并讲解一下 CPU/GPU 和内存在渲染中的职责。
渲染管线主要分为三大阶段应用阶段/几何阶段/光栅化阶段,这里将各个阶段简单讲解:
1.1
应用阶段
这个阶段主要在 CPU 中,从 CPU 中整理好渲染数据,并将数据发送给 GPU。
1.2
几何阶段
通过对输入的渲染图元进行处理,这一阶段将会输出屏幕空间的二维顶点坐标,深度值等信息并传递给下一阶段。
1.3
光栅化阶段
将点线面等几何概念实体化成像素,这一阶段会使用上一阶段传递的数据渲染出最终的图像。
此图中很浅显的标识了 3Dmesh 和 2Dtexture 之间的关系。
3Dmesh 提供定点数据进去 screen space 空间绘制之后转换为片段着色器中填充,而后再由 TEXTER 根据坐标填充颜色,最后渲染到显示器上。
2.名词解释
2.1
Drawcall
Drawcall是CPU对底层图形绘制接⼝的调⽤命令GPU执⾏渲染操作,渲染流程采⽤流⽔线实现,CPU和GPU并⾏⼯作,它们之间通过命令缓冲区连接,CPU向其中发送渲染命令,GPU接收并执⾏对应的渲染命令。
2.2
合批
动态合批与静态合批其本质是将多次绘制请求,在允许的条件下进行合并处理,减少CPU对GPU绘制请求的次数,达到提高性能的目的。
2.3
图集
图集是将很多零碎的2D小图整合成一张大图,方便unity渲染合批,降低渲染消耗。
3.优化概述
了解完 CPU/GPU/内存的职责之后就可以对每一个模块进行优化了。Unity 性能优化细节较多,每一个功能点都可以单独写一篇文章。
这里先了解一下 Unity 大致有哪些优化分类和优化点:
模块 | 优化点 |
CPU | 渲染 物体顶点和图像的绘制 降低 DrawCall 批处理 合并图集 压缩资源 动画 物体动画/骨骼动画 物理 物理计算,重力和碰撞 UI UI 的绘制和响应事件 合批 动静分离 粒子 粒子的生命周期和绘制 IO 文件的操作和读取 GC 内存的回收和释放 场景/资源的加载/卸载 代码 代码的调用次数和调用耗时 |
GPU | 填充率 像素的复杂度 几何复杂度 GPU 显存带宽 减少顶点数量,简化计算复杂度 压缩图片/Mipmap,以适应显存带宽 LOD/ 遮挡剔除/光照贴图等 |
内存 | 模型/纹理 尺寸 格式 Read & Write 规范好模型面数,纹理尺寸和格式 网络资源 Bundle 图片 数据 管理好网络加载和释放 托管堆 高频率调用 string 拼接 部分 UnityAPI 内存 避免一次性堆内存的过大分配 避免不必要的内存开销 |
其他 | 包体优化点 |
4.工具/方法论
工欲善其事,必先利其器。选择好的工具和方法论可以事半功倍,这里整理一下我平时使用的工具和总结出的方法论。
4.1
工具
• Profiler UnityEditor 性能分析工具
• UPR 官方性能分析工具
• UWA 第三方性能分析工具
• Memprofile 内存检查工具
► 其他还有一些移动端和 PC 调试工具:
• mali Graphic debugger
• snapdragon profile
• ADB & AndroidStudio
• Xcode GPU Frame Caputre
4.2
方法论
► 量化
• 优化前先记录一下性能数据,在优化后做一下对比,并量化你的优化收益。
• 防止做负优化。
► 隔离法
• 隔离可疑区域和代码,然后比较,逐步排查,缩小问题范围。
► 对比法
• 记录数据,用正常数据和性能变化之后的数据进行对比,定位问题。
► 项目前期的规范确定
• 需要适配的机型,参考按照手机/显卡使用率,给定一个最低配置。
• 模型面数,材质大小和格式。
• 尽早使用 AssestBundle 管理资源。
• Unity 版本与各个 SDK 版本。
• 逻辑层架构与底层通用功能。
► 经验
• 让正确的程序快,比让快的程序正确更简单,所以应该先进行功能迭代,再进行优化。
• 图形学第一定律:如果它看上去是对的,那么它就是对的,可以用一些技巧让画面正确,从而达到优化的目的。
5.数科产品 VI 销冠神器
性能优化介绍
5.1
产品介绍
VI 销冠神器,作为辅销工具解决经销商在售卖场景中的痛点,利用 AR 虚拟现实技术打造辅销工具,高效支持产品售卖,满足厂商定制需求。
5.2
问题回顾
在多次迭代中产品和客户反馈了以下几个问题:
1. AR 功能识别率低,扩展性不足;
2.包体过大;
3.帧率低;
4.发热量大;
5.内存占用过高。
由于我刚接手销冠项目,对项目的熟悉程度不足,所以决定先做一些投入时间少、优化收益大的、比较宽泛的优化,等之后再做一些需要投入更多时间精力的、比较细碎优化。
针对反馈的问题我做了以下工作:
5.3
AR 优化
► 问题分析:
我分析了一下 AR 功能性能指标差主要是由以下几个原因导致的:
1. 代码耦合严重;
2. 实车绑定和平面识别速度过慢;
3. 实车绑定训练文件过大;
4. 安卓 iOS 代码写在一个类里面耦合严重;
5. 扫车和扫平面同时创建内存占用较多。
► 优化过程:
项目中使用 2 个场景用来区分 EasyAR 和 Vuforia减少到 1 个场景,安卓和 iOS 在自己的类里实现逻辑,初始化时判断平台,通过继承实现每个端的相关逻辑,可以处理一些复杂情况。比如安卓平台的 Vuforia 和 EasyAR 切换 和 iOS 平台的扫描车和地面切换的问题。
通过异步和更改加载时机来解决扫平面和扫车的内存峰值,配置了一个 Editor 环境下模拟 AR 环境的设置,可以很方便在 Editor 环境下复现问题,省下经常打包到手机上的时间,训练模型优化 模型减面后重新训练一版,在不降低识别精度的情况下减少包体大小。
► 优化结论:
1. 降低了 28mb 的包体大小;
2. 提高了平面和实车的识别率和稳定性;
3. 降低了代码耦合,解决了遗留的 bug;
4. 配置了 Editor 模拟环境,提高了开发效率和 Debug 效率。
5.4
贴图优化
► 问题分析:
在项目中发现有一些材质的图片尺寸较大,而且一张图片重复导入了多次。
► 优化过程:
跟美术人员反馈后,在他们新制作的材质包中做了优化,使用了新的 shader,用更低的内存占用实现了更好的效果。
► 优化结论:
1. 在提高美术效果的同时降低渲染压力;
2. 降低发热,提高项目的稳定性;
3. 降低 200m 左右的内存占用,实现了更好的美术效果。
5.5
内存优化
► 问题分析:
接手项目是 AR 加载时内存峰值 iPhone7Plus 会经常崩溃,并且打开 WebView 的时候也会超出内存限制引发项目崩溃并且项目发热严重,帧率不稳定。
经过细致排查发现主要是因为:
1. 各个模块加载时的资源抢占;
2. 多张 4k 材质贴图未压缩 渲染数据包过大;
3. 精细的模型和过高的帧率。
► 优化过程:
解耦各个模块的依赖,错开初始化时机,降低内存峰值;使用新的材质实现方式,用更小的图片实现更好的美术效果;给美术提供减面思路,并适度降低帧率。
► 优化结论:
1. 减少内存峰值;
2. 减少总内存占用 200m 左右。
5.6
发热优化
► 问题分析:
销冠项目发热部分是来源于
1. 摄像头的发热量;
2. CPU/GPU 占用过高;
3. 渲染次数多;
4. 渲染数据大;
5. 帧率高。
发热量优化一般要做到两点:
降低渲染次数和降低每次渲染的数据大小。
► 优化过程:
设置项目帧率至 45 帧,默认 Unity 不限制帧率,一般会跑满手机全部性能,较高的帧率会带来大量发热;降低渲染次数 UI 图片打成图集降低 drawcall;压缩材质图片 项目中用到了一些过大的材质图片,已反馈给模型制作方进行材质图片压缩。
► 优化结论:
1. CPU 温度从 65 度降到 55 度;
2. 发热开始时间明显延后。
5.7
包体优化
► 问题分析:
接手销冠项目时包体大小为 210mb
这里的包体大小用安卓的 apk 大小来举例销冠项目包体占用的大头有:
1. AR Vuforia 和 EasyAR 的 SDK 都会占用 20mb 左右的包体大小.Vuforia 的训练文件又会占用了 50mb 共计 90mb;
2. 打包到本地的材质贴图和模型 共计 90mb;
3. UI 图片 15mb 左右;
4. Unity 引擎和代码逻辑 20mb 左右。
► 优化过程:
剔除项目无用图片资源 212m→206m,Vuforia 训练模型减面 206m→170m,本地美术资源上传网络 按需下载 170m→80m。
► 优化结论:
包体从 210MB 降低到 80MB。
6.总结
随着工作经验的不断增长,发现优化和架构才是程序员的核心竞争力。在初中级程序期,我也烦恼过为什么要去了解那么多底层和算法知识。
现在看来,这些知识都是前人无数次迭代和试错总结出来的。在学习的同时也掌握了一套自己的经验,在之后的工作中写出更健壮和高效的代码。
销冠项目只做了部分优化,还有很多细节可以继续优化。目前销冠项目由其他同事负责维护,现在我所在的全息项目也到了要优化的阶段。未来提升方向是在不牺牲画面效果的同时提升程序性能,着重资源管理和 Shader 的开发。
限于作者水平,难免会有疏漏和错误,欢迎指正,共同交流。
优质文章分享
关于优化已经有很多非常好的文章,这里推荐一些:
[1] Unity 性能优化总结—CPU篇
https://zhuanlan.zhihu.com/p/21913747
[2] Unity 优化之 GPU 优化
https://zhuanlan.zhihu.com/p/47056964
[3] Unity 游戏中,在做性能优化时怎么准确判断是内存、CPU、GPU 瓶颈呢?
https://www.zhihu.com/question/522171023
[4] Unity 移动端游戏性能优化简谱之 常见游戏内存控制
https://blog.uwa4d.com/archives/EDU_Performance2.html
[5]如何定位游戏发热问题
https://blog.uwa4d.com/archives/TechSharing_300.html
[6] Unity 移动端游戏性能优化简谱之前言
https://blog.uwa4d.com/archives/EDU_Performance.html
[7] Unity 官方 Profiler 文档
https://docs.unity3d.com/cn/current/Manual/ProfilerMemory.html
[8] C#代码优化:拯救你的 CPU 耗时
https://zhuanlan.zhihu.com/p/348544667
[9] 基础且直白的 Unity 渲染
https://zhuanlan.zhihu.com/p/457706826
UWA 性能优化系列:
[1] Unity 性能优化系列—渲染模块
https://blog.uwa4d.com/archives/UWA_ReportModule1.html
[2] Unity 性能优化系列—加载与资源管理
https://blog.uwa4d.com/archives/UWA_ReportModule2.html
[3] 粒子系统优化——如何优化你的技能特效
https://blog.uwa4d.com/archives/UWA_ReportModule3.html
[4] Unity 性能优化系列—Lua代码优化
https://blog.uwa4d.com/archives/UWA_ReportModule4.html
[5] Unity 性能优化系列 — 资源内存泄漏
https://blog.uwa4d.com/archives/UWA_ReportModule5.html
[6] Unity 性能优化 — 动画模块
https://blog.uwa4d.com/archives/UWA_ReportModule6.html
[7] Unity 性能优化 — 物理模块
https://blog.uwa4d.com/archives/UWA_ReportModule7.html
[8] Unity 性能优化 — UI模块
https://blog.uwa4d.com/archives/UWA_ReportModule8.html
作者简介
胡春源
■ 主机厂事业部-创新项目团队。
■ 2022年2月入职汽车之家,先后负责VI销冠神器和全息仓的架构、优化、功能开发等工作。现在主要负责全息仓的架构和功能的相关工作。
阅读更多:
▼ 关注「之家技术」,获取更多技术干货 ▼