优化思路
个人优化原则:
1. 减少总量
2. 空间、时间互换
3. 由浅入深
1. 减少总量:
尽量减少内存和 CPU 占用的总量
2. 空间、时间互换:
内存和 CPU 可以互换、CPU 和 GPU 可以互换
3. 由浅入深:
先优化小的细节再优化大的结构
大致手段:
1. 降 CPU
2. 降内存
3. 内存换 CPU
4.CPU 换内存
5.GPU 换 CPU
6. 磁盘换内存
优化思路说明:
尽量减少占用的内存 (资源体积) 和 CPU(计算量),是一切的前提,首先着重减少总量才能更好的进行后续细节的优化。
由于内存比 CPU 便宜多了,所以一般都是内存换 CPU 的,内存不够时再用 CPU 换内存。
比如利用对象池缓存对象,可以省略加载资源、实例化、销毁实例、卸载资源的步骤,可以明显降低 CPU 的消耗。
利用 Loading 进度条按需加载资源,可以减少内存峰值,大量节约内存。
通常来说先优化细节,如果细节优化已经做的很好,没什么太多潜力可以挖了,性能还是消耗太大,那么就需要考虑重构结构了。
性能分析:
使用 Profiler 性能分析器首先确定性能瓶颈出现在哪里,定位性能问题出现的根本原因,按照具体原因去做优化。
通常来说,性能问题大致出现在两个方面:
1. 细节不够好(资源问题、插件问题、代码写法问题)
2. 结构不够好(框架问题、底层 API 问题)
细节问题解决成本低,可以独立调整,对其他部分影响小,可以批量解决。
结构问题解决成本高,牵一发动全身,对其他部分影响大,需要大修、大测。
由于游戏整体是由各个细节组成的,所以当细节做的不够好时,整体也会显现出问题。
反之当结构不够好时,细节即使做的很好,游戏整体表现出的性能也不会太好,两者是相辅相成的。
我的建议是:用严格认真的态度控制细节,用丰富的经验积累出可靠的结构。
前者靠态度,后者靠经验。当我们经验不多时,应该依靠态度严控细节,当我们经验足够时,两方面都要兼顾。
多读官方 API:
多读官方 API, 多读官方 API 多, 读官方 API。重要的事情说三遍,不要重复造轮子。Unity 中有很多性能细节问题都出现在功能不熟悉上,没玩明白导致的,熟悉官方 API 可以让我们事半功倍。C#代码也一样,也要熟悉 C# 官方 API。
优化内存
Unity 中 资源占用的内存量比代码高的多,只要代码不往死掉写,一般不会占用太高内存,我们要特别注意资源的内存占用。
Unity 资源内存占用排行榜
1. 贴图 Textures
2. 动画 AnimationClips
3. 网格 Meshes
4. 音频 AudioClips
5. 材质 Materials
资源内存占用说明:
名称 | 单个体积 | 同时使用数量 | 总体内存占用 | 内存占用说明 |
---|---|---|---|---|
贴图 | 大 | 很多 | 很大 | 占用超级大户 远超其他资源(超级土豪 VIP 熟客 需重点关照 利润大) |
动画 | 大 | 多 | 大 | 占用大户 时间越长 关键点越多体积越大(普通顾客 认真对待 利润中) |
网格 | 中 | 中 | 中 | 占用中等 和精细度有关 一般内存问题不会出现在它身上(普通游客 利润小) |
音频 | 大 | 少 | 小 | 占用大 压缩比高 ogg 加进内存后 体积增大 10 倍(土豪游客 出现一次狠宰) |
材质 | 很小 | 少 | 很小 | 占用很小 数量也少 (邻居 别指望从它身上赚钱了) |
1. 减少贴图占用内存
内存占用超级大户,史前怪兽级别的,要优化内存先从优化贴图格式开始。
按照下面 3 步设置,可以极大降低贴图占用内存。
1. 降低分辨率
2. 拆分透明通道
3. 调整压缩格式
4. 禁用 Mipmap
5. 启用 Use Crunch Compression
1. 降低分辨率(Max Size):
根据 Game 摄像机距离物体最近时,物体所占的像素大小 (QQ 截图),来确定最大分辨率。
一般美工或 Asset Store 上下载的资源很可能是高清资源,1024×1024、2048×2048 或更大,我们需要根据实际使用的尺寸确定。
2048×2048 降低为 1024×1024 后 内存会降低为原来的 1 /4 极大降低内存占用 这里是是大头 要控制好。
(图片大小和像素有关 像素点数 = 宽 x 高 = 面积 宽高各变为 1 /2 面积变为 1 /4)
2. 拆分透明通道(Alpha):
不需要 Alpha 通道的一定要去除 Alpha 通道 因为带 Alpha 通道的贴图 Unity 会默认选择 RGBA 格式。
如果不能剔除 Alpha 要把 format 由 RGBA 格式选为 RGB 格式 以减小内存占用。
非渐变的透明贴图 可以调成 RGB + 1bit alpha 的格式 拆分 alpha 通道。
(RGBA 一般各通道是平均分 每份 1 /4 剔除一个通道 体积减少 1 /4)
3. 调整压缩格式(Compression):
尽量选用当前平台支持的最高压缩格式,不要轻易使用 RGBA32 格式,更不要使用不压缩格式,内存天差地别。
只要启用 Compression 选项,Unity 会自动帮我们选用合适的压缩格式 要注意的是压缩格式的支持都是有条件限制的。
当不能使用更好的压缩格式时,Unity 会出现提示,告诉我们哪里有问题。对于压缩格式:一般要注意以下两个问题。
(1)不需要 Alpha 透明通道的贴图 请在 PS 里剔除。
(2)高压缩比格式要求图片宽高是 2 的倍数 (4 的倍数更好) 宽高不能被 2 整除,会导致不能用高压缩比的格式。
宽高禁止出现奇数,必须都是偶数,打成图集的图片是 2 的倍数即可,单独使用的图片宽高要是 4 的倍数。
以一张 512×512 分辨率的图片为基准 测试不同平台 不同压缩格式占用的内存:
PC 常用图片格式:DXT
图片格式 | 512×512(启用 Mipmap) | 1024×1024(启用 Mipmap) | 图片质量 | 内存(压缩比) | 说明 |
---|---|---|---|---|---|
RGBA 32 bit | 1M(1.3M) | 4 M(5.3M) | 最高 | 最大(1) | 透明高清无压缩 最靠后选择 |
ARGB 16 bit | 0.5M(0.7M) | 2 M(2.7M) | 中 | 中(1/2) | RGBA32 阉割版 靠后选择 |
RGB(A) BC7 | 256KB(341.4KB) | 1M(1.3M) | 中高 | 小(1/4) | 透明高清高压缩 次优先选择 |
RGBA DXT5 | 256KB(341.4KB) | 1M(1.3M) | 中 | 小(1/4) | 透明中清高压缩 最优先选择 |
RGB 24 bit | 0.8M(1M) | 3M(4M) | 高 | 很大(3/4) | 不透明高清无压缩 最靠后选择 |
RGB 16 bit | 0.5M(0.7M) | 2M(2.7M) | 中 | 中(1/2) | RGB24 阉割版 靠后选择 |
RGB DXT1 | 128KB(170.7KB) | 0.5M(0.7M) | 中 | 很小(1/8) | 不透明中清高压缩 最优先选择 |
RGB(A) BC7:高质量高压缩格式 但是 mac 上不兼容
Android 常用图片格式:ETC
图片格式 | 512×512(启用 Mipmap) | 1024×1024(启用 Mipmap) | 图片质量 | 内存(压缩比) | 说明 |
---|---|---|---|---|---|
RGBA 32 bit | 1M(1.3M) | 4 MB(5.3M) | 最高 | 最大(1) | 透明高清无压缩 最靠后选择 |
ARGB 16 bit | 0.5M(0.7M) | 2 MB(2.7M) | 中 | 中(1/2) | RGBA32 阉割版 靠后选择 |
RGBA ETC2 8 bits | 256KB(341.4KB) | 1 MB(1.3M) | 中 | 小(1/4) | 透明中清高压缩 最优先选择 |
RGB 24 bit | 0.8M(1M) | 3M(4M) | 高 | 很大(3/4) | 不透明高清无压缩 最靠后选择 |
RGB 16 bit | 0.5M(0.7M) | 2M(2.7M) | 中 | 中(1/2) | RGB24 阉割版 靠后选择 |
RGB ETC2 4 bits | 128KB(170.7KB) | 0.5M(0.7M) | 中 | 很小(1/8) | 不透明中清高压缩 最优先选择 |
RGB ETC 4 bits | 128KB(170.7KB) | 0.5M(0.7M) | 中 | 很小(1/8) | 不透明中清高压缩 次优选择 |
IOS 平台常用图片格式:PVRTC
图片格式 | 512×512(启用 Mipmap) | 1024×1024(启用 Mipmap) | 图片质量 | 内存(压缩比) | 说明 |
---|---|---|---|---|---|
RGBA 32 bit | 1M(1.3M) | 4 MB(5.3M) | 最高 | 最大(1) | 透明高清无压缩 最靠后选择 |
ARGB 16 bit | 0.5M(0.7M) | 2 MB(2.7M) | 中 | 中(1/2) | RGBA32 阉割版 靠后选择 |
RGBA PVRTC 4 bits | 128KB(170.8KB) | 0.5M(0.7M) | 低 | 很小(1/8) | 透明低清高压缩 最优先选择 |
RGBA ASTC 6×6 block | 115.6KB(154.7KB) | 456.9KB(0.6M) | 中 | 很小(~1/8) | 透明中清高压缩 iPhone6 之后首选 |
RGB 24 bit | 0.8M(1M) | 3M(4M) | 高 | 很大(3/4) | 不透明高清无压缩 最靠后选择 |
RGB 16 bit | 0.5M(0.7M) | 2M(2.7M) | 中 | 中(1/2) | RGB24 阉割版 靠后选择 |
RGB PVRTC 4 bits | 128KB(170.8KB) | 0.5M(0.7M) | 低 | 很小(1/8) | 不透明低清高压缩 最优先选择 |
RGB ASTC 6×6 block | 115.6KB(154.7KB) | 456.9KB(0.6M) | 中 | 很小(~1/8) | 透明中清高压缩 iPhone6 之后首选 |
PVRTC:IOS 原生支持的一种压缩格式 优点是:高压缩比 兼容性好 缺点是:有损压缩 图片质量较差,对于透明像素的边缘和渐变的透明度有特别明显的失真。
ASTC:IOS 支持的一种新的压缩格式 优点是:比 PVRTC 更高的压缩比和质量,透明贴图质量更高 缺点是:兼容性差 iPhone6 才开始支持该格式,iPhone5 和之前不支持该格式。
参考资料:
《干货:Unity 游戏开发图片纹理压缩方案》https://www.jianshu.com/p/f7c…
《Unity3D 的图片压缩格式详解》https://www.jianshu.com/p/bec…
《Unity3D~ 纹理格式》https://www.cnblogs.com/rayya…
《Unity 中一个简单的图形优化指导》http://gad.qq.com/program/tra…
4. 禁用 Mipmap
Mipmap 相当于 Texture 的 LOD 启用后会生成多级纹理 会占用更多的内存 好处是会让贴图看起来更平滑。
启用该选项会生成多级小贴图 内存会增加 1 /3。
5. 启用 Use Crunch Compression
Crunch 是 Unity 支持的最新压缩格式,压缩比非常高,如果你用其他格式,图片依然很大的话,这个格式将会成为你的神兵利器。
Crunch 支持 Android 和 IOS 平台,能把图片压的很小,但图片质量有损失,可以通过调节质量百分比来解决。
Crunch 在 Editor 下,计算压缩的时间很长,77 张 2048 的图片要压缩 5~8 分钟左右。
对于大量贴图的更新来说,整个团队的开发人员都要消耗相当长的时间来导入贴图,十分痛苦 很容易拉仇恨(说的就是我自己)。
参考资料:
《Unity 性能优化之内存 - 贴图格式优化》https://segmentfault.com/a/11…
《Unity 优化(一):图形优化》https://gameinstitute.qq.com/…
《[Unity 优化] unity 图片 mipmap》https://www.jianshu.com/p/651…
《Unity 2017.3 中的 Crunch 纹理压缩库》https://www.sohu.com/a/204935…
《Unity 官方文档 Texture》https://docs.unity3d.com/Manu…
2. 减少动画占用内存
总结一下优化动画的手段:
1. 减小动画长度
2. 减少骨骼数量
3. 减少关键帧密度
4. 减少动画精度
1. 减小动画长度
有些动画实际使用的的长度,远小于动画时长,如果有被加快使用的动画,应该考虑改短动画,降低大小,Animator 里加快速度不会减少动画大小。
2. 减少骨骼动画
动画导入后,查看有无无效的骨骼点,删除这些节点可以降低动画大小。
(1)Animation 里 骨骼点变成黄色说明缺少该骨骼点,需要确定是骨骼点丢失还是不需要这些骨骼点,如果动画正常,则说明这些骨骼点无效可以删除。
(2)注意 IK 骨骼点 如果不需要使用反向动力学功能,而动画里又包含了 IK 骨骼点, 则删除这些骨骼点(通常是美工做完动画忘删 IK 了)。
3. 减少关键帧密度
启用 FBX > Animation 选项 > Anim.Compression 选项 > Keyframe Reduction
Keyframe Reduction 官方文档翻译:减少导入的冗余关键帧。如果选择,将显示动画压缩错误选项。这将影响文件大小(运行时内存)和如何评估曲线。
4. 减少动画精度
Unity 存储 Animation 的数值精度比较高,可以通过减少数值精度的手段,降低动画大小。
参考资料:
《Unity 骨骼动画资源解析与优化》https://www.cnblogs.com/damow…
《unity 性能优化之降低动画文件的大小》https://blog.csdn.net/rhett_y…
《Unity 优化翻译官方文档(三) Animation Clips》https://blog.csdn.net/dengshu…
3. 减少网格占用内存
1. 减少顶点
2. 开启 Optimize Mesh 选项
3. 关闭 Mesh Compression
1. 减少顶点 Vertex
减少顶点会显著的提升网格的性能,减少内存的占用,通常来说,在可以实现美术效果的前提下,顶点越少越好。
2. 开启 Optimize Mesh 选项
官方文档翻译:为了更好的 GPU 性能,顶点和索引将被重新排序。需要严格顶点排序的技术,如网格变形或特殊的粒子网格发射器效果,应该禁用此选项。
3. 关闭 Mesh Compression
开始网格压缩可能会导致 Optimize Mesh 失败,占用更大的内存。
参考资料:
《Unity 的 Mesh 压缩:为什么我的内存没有变化?》https://www.cnblogs.com/muron…
4. 减少音频占用内存
音频同时使用的数量较少,但是压缩比率大,默认音频格式加进内存后,体积会增大 10 倍。
对于较大的音频文件 (超过 200KB),要特别注意。
Load Type 改为 Streaming,可以极大降低内存占用。
建议较长的音频使用.mp3 或.ogg 格式,较短的音频使用.wav 或.aiff 格式。
参考资料:
《Unity 优化翻译官方文档(四) —— Audio Clip》https://blog.csdn.net/dengshu…
5. 减少材质占用内存
材质性能排行(由高到低):
1.Unlit 仅为纹理,光线不产生效果
2.VertexLit 顶点光照
3.Diffuse 漫反射
4.Normal Mapped 法线贴图
5.Specular 高光
6.Normal Mapped Specular
7.Parallax Normal Mapped
8.Parallax Normal Mapped Specular
尽量用性能消耗更小的 Shader 来实现效果,复杂的 Shader 需要专人定制、管理和维护,写好 Shader 需要时间和经验的积累。
参考资料:
《Unity3D Shader 性能排行》https://www.cnblogs.com/tim-u…
《UnityShader 学习资料推荐》https://blog.csdn.net/wwlcsdn…
《Amplify Shader Editor 手册(中文版)》https://blog.csdn.net/Debugge…
优化 CPU
1. 降低 DrawCall
2. 注意代码规范
3. 内存换 CPU
4. 使用异步代替同步
1. 降低 DrawCall:
消耗 CPU 过大的情况很容易出现在图形渲染上,合并批处理,降低 DrawCall 可以极大的提升性能。比如使用动、静态批处理,GPU Instance 技术。
2. 注意代码规范:
良好的代码规范会让你获得更好的性能,并且避免很多陷阱,减少入坑的几率,节约时间。多读官方 API,避免重复造轮子。
3. 内存换 CPU:
CPU 不够时,不但可以想方法降低 CPU 的消耗,也可以考虑用内存换 CPU。使用对象池就是一种常见的内存换 CPU 的手段。
4. 使用异步代替同步:
使用异步 Async(非阻塞式)代替同步 Sync(阻塞式),可以优化用户体验。比如加载时用异步加载,显示进度条就属于这种方式。
但是通常异步比同步消耗的时间更多,遇到的问题更多,所以要合理使用异步和同步。
参考资料:
《[Unity 优化]减少 DrawCall:批处理》https://blog.csdn.net/lyh916/…
《Unity 官方文档 -DrawCallBatching》https://docs.unity3d.com/Manu…
《Unity GPU Instance(大量相同网格物体合批)》https://segmentfault.com/a/11…
《Unity 对象池》https://blog.csdn.net/wangjia…
《Unity3D 研究院之异步加载游戏场景与异步加载游戏资源进度条》https://www.xuanyusong.com/ar…