前言
介绍:Unity3D为我们提供了一个强大的性能分析工具Profiler。今天我们就使用Profiler来详细分析一下官方例子AngryBots的内存使用信息数据。(废话不多少咱自己来干货!)
首先Mono的Simple
Uesd Total :当前帧的Unity内存,Mono内存,GfxDriver内存,Profiler内存以及额外内存的总和。
Reserved Total:系统在当前帧申请的总体物理内存
Total System Memory Usage:当前帧的虚拟内存使用量
GameObjects in Scene:当前帧场景中的GameObject数量
Total Objects in Scene:当前帧场景中的Object数量(除GameObject外,还有各种Component)
Total Object Count:所有Object数量
(这里主要可以清晰的看到一些大致内存消耗,我这里就是拿了一个测试项目所以看起来内存会少一些。)
Mono的Detaile
Profiler中的Not Saved指的是项目中通过代码生成的各种资源记录
DontSave:保留对象到新场景
功能说明:此属性的功能是用来设置是否将Object对象保留到新的场景(Scene)中,如果使用HideFlags.DontSave,则Object对象将在新场景中被保留下来,对其使用说明如下。
(1)如果GameObject对象被HideFlags.DontSave标识,则在新scene中GameObject的所有组件将被保留下来,但其子类GameObject对象不会被保留到新scene中。
(2)不可以对GameObject对象的某个组件如Transform进行HideFlags.DontSave标识,否则无效。
(3)即使程序已经退出,被HideFlags.DontSave标识的对象会一直存在于程序中,造成内存泄漏,对HideFlags.DontSave标识的对象在不需要或程序退出时需要使用DestroyImmediate手动销毁。
(这样看来这一部分是很重要的特别是当标识被改动后如果没有做到及时的清理就会很麻烦。)(
Profiler中的Other
ManagedHeap 表示的是Mono所使用的托管堆内存,C#上任何的申请托管的内存都会在这个上面申请。
ManagedHeap.UsedSize是项目逻辑代码在运行时申请的堆内存,该选项只能通过优化代码来进行降低。
ManagedHeap.UsedSize过大,一方面可能会影响一次GC的耗时;另一方面也可能反映出脚本中不合理的GC Alloc。
ManagedHeap.UsedSize:托管堆使用大小(表示上次GC到目前为止所分配的堆内存量)。移动游戏建议不超过20M。
优化方法一般如下:
尽可能地复用变量,减少new的次数;
使用StringBuilder代替String连接,使用for代替foreach;
对于局部变量或非常驻变量,尽可能使用Struct来代替Class。
ManagedHeap.ReservedUnusedSize:托管堆预留不使用内存大小,只由Mono使用。
SerializedFile: AssetBundle加载时产生的序列化信息,一般为LoadFromCacheOrDownload、LoadFromFile和New WWW加载本地AssetBundle文件所致,
SerializedFile中记录的是AssetBundle的序列化信息,而不是其包含资源的内容,因此,其大小要小于或远小于资源的实际内存。
实测SerializedFile所占的内存远小于bundle的实际内存,但是目前还是很容易上10M的。
ShaderLab:Unity自带的着色器语言工具相关资源。
GfxClientDevice:GFX(图形加速\图形加速器\显卡 (GraphicsForce Express))客户端设备。
PersistentManager.Remapper:持久化数据重映射管理相关
Profiler中的Scene Memory
如果load一些asset再回到原来的UI,这部分基本没有变化。因为它存储的是当前的场景中各个方面的内存占用情况。
包括GameObject、所用资源、各种组件以及GameManager等(一般情况通过AssetBundle加载的不会显示在这里,实例的对象还是会显示)
优化: 注意网格模型的点面数,能合并的mesh尽量合并。
Profiler中的Assets
Texture2D: 2D贴图及纹理。有以下几点可以优化:
1.许多贴图采用的Format格式是ARGB 32 bit所以保真度很高但占用的内存也很大。在不失真的前提下,适当压缩贴图,使用ARGB 16 bit就会减少一倍,如果继续Android采用RGBA Compressed ETC2 8 bits(iOS采用RGBA Compressed PVRTC 4 bits),又可以再减少一倍。把不需要透贴但有alpha通道的贴图,全都转换格式Android:RGB Compressed ETC 4 bits,iOS:RGB Compressed PVRTC 4 bits。
2.当加载一个新的Prefab或贴图,不及时回收,它就会永驻在内存中,就算切换场景也不会销毁。应该确定物体不再使用或长时间不使用就先把物体制空(null),然后调用Resources.UnloadUnusedAssets(),才能真正释放内存。
3.有大量空白的图集贴图,可以用TexturePacker等工具进行优化或考虑合并到其他图集中。
AudioManager:音频管理器随着音频文件的增多而增大。
AudioClip:音效及声音文件。重点优化对象,播放时长较长的音乐文件需要进行压缩成.mp3或.ogg格式,时长较短的音效文件可以使用.wav 或.aiff格式。
Cubemap:立方图纹理。这个一般在天空盒中比较常见
Mesh:模型网格。主要检查是否有重复的资源,还有尽量减少点面数。
Builtin Resources:这些都是Unity的一些内部资源,对于项目内存没有什么分析价值,所以我就暂时不对其进行分析了。
最后做个总结在项目中一般要关注的地方,
1.ManagedHeap.UsedSize: 移动游戏建议不要超过20MB.
2.SerializedFile: 通过异步加载(LoadFromCache、WWW等)的时候留下的序列化文件,可监视是否被卸载.
3.WebStream: 通过异步WWW下载的资源文件在内存中的解压版本,比SerializedFile大几倍或几十倍,不过我们现在项目中展示没有。
4.Texture2D: 重点检查是否有重复资源和超大Memory是否需要压缩等.
5.AnimationClip: 重点检查是否有重复资源.
6.Mesh: 重点检查是否有重复资源.