转载自:http://blog.csdn.NET/yangyy753/article/details/47025205 Unity3D为我们提供了一个强大的性能分析工具Profiler。今天我们就使用Profiler来详细分析一下官方例子AngryBots的内存使用信息数据。 首先打开Profiler选择Memory选项,在游戏运行的某一帧查看Detailed选项数据(Simple模式的数据很直观,可以知道内存大体被哪部分占用了,网上也有很多相关介绍,我就不再啰嗦了),如下图所示:
选中后,unity会自动获取这一帧的内存占用数据项,主要分为:Other、Assets、BuiltinResources、Scene Memory、NotSaved这五大部分,下面我们就来一一分析。
记录数据项很多,篇幅时间有限,我们就专挑占用大小排行榜靠前的几项来详细分析吧。
Ricky:我试着修改了一下Stripping Level似乎没什么改变,感觉虽占用内存大但不会影响游戏运行。我们暂时忽略它吧(- -)!
Ricky:虽占用较大内存,但这也是必备项,没办法优化。继续忽略吧(- -)!!
Ricky:重点监控对象,不要让它超过20MB,否则可能会有性能问题!
Ricky:这个东西大家都比较熟悉了,忽略它吧。
Ricky:重点监控对象,这里就是你要监控的哪些预设在序列化中在内存中占用大小,根据需求进行优化。
Ricky:与持久化数据相关,比如AssetBundle之类的。注意监控相关的文件。
Ricky:无法优化。
Ricky:重点优化对象,有以下几点可以优化:
Ricky:随着音频文件的增多而增大。
Ricky:重点优化对象,播放时长较长的音乐文件需要进行压缩成.mp3或.ogg格式,时长较短的音效文件可以使用.wav 或.aiff格式。
Ricky:这个一般在天空盒中比较常见,我也不知道如何优化这个。。。
Ricky:主要检查是否有重复的资源,还有尽量减少点面数。
Ricky:注意网格模型的点面数,能合并的mesh尽量合并。
Ricky:这些都是Unity的一些内部资源,对于项目内存没有什么分析价值,所以我就暂时不对其进行分析了。
1)ManagedHeap.UsedSize: 移动游戏建议不要超过20MB. 2)SerializedFile: 通过异步加载(LoadFromCache、WWW等)的时候留下的序列化文件,可监视是否被卸载. 3)WebStream: 通过异步WWW下载的资源文件在内存中的解压版本,比SerializedFile大几倍或几十倍,不过我们现在项目中展示没有。 4)Texture2D: 重点检查是否有重复资源和超大Memory是否需要压缩等. 5)AnimationClip: 重点检查是否有重复资源. 6)Mesh: 重点检查是否有重复资源.
1.Device.Present: 1)GPU的presentdevice确实非常耗时,一般出现在使用了非常复杂的shader. 2)GPU运行的非常快,而由于Vsync的原因,使得它需要等待较长的时间. 3)同样是Vsync的原因,但其他线程非常耗时,所以导致该等待时间很长,比如:过量AssetBundle加载时容易出现该问题. 4)Shader.CreateGPUProgram:Shader在runtime阶段(非预加载)会出现卡顿(华为K3V2芯片). 5)StackTraceUtility.PostprocessStacktrace()和StackTraceUtility.ExtractStackTrace(): 一般是由Debug.Log或类似API造成,游戏发布后需将Debug API进行屏蔽。 2.Overhead: 1)一般情况为Vsync所致. 2)通常出现在Android设备上. 3.GC.Collect: 原因: 1)代码分配内存过量(恶性的) 2)一定时间间隔由系统调用(良性的). 占用时间: 1)与现有Garbage size相关 2)与剩余内存使用颗粒相关(比如场景物件过多,利用率低的情况下,GC释放后需要做内存重排) 4.GarbageCollectAssetsProfile: 1)引擎在执行UnloadUnusedAssets操作(该操作是比较耗时的,建议在切场景的时候进行)。 2)尽可能地避免使用Unity内建GUI,避免GUI.Repaint过渡GCAllow. 3)if(other.tag == a.tag)改为other.CompareTag(a.tag).因为other.tag为产生180B的GC Allow. 4)少用foreach,因为每次foreach为产生一个enumerator(约16B的内存分配),尽量改为for. 5)Lambda表达式,使用不当会产生内存泄漏. 5.尽量少用LINQ: 1)部分功能无法在某些平台使用. 2)会分配大量GC Allow. 6.控制StartCoroutine的次数: 1)开启一个Coroutine(协程),至少分配37B的内存. 2)Coroutine类的实例 -> 21B. 3)Enumerator -> 16B. 7.使用StringBuilder替代字符串直接连接. 8.缓存组件: 1)每次GetComponent均会分配一定的GC Allow. 2)每次Object.name都会分配39B的堆内存.
Ricky Yang个人原创,版权所有,转载注明,谢谢。http://blog.csdn.Net/yangyy753 |
|