1.Unity内存开销介绍
就目前基于Unity引擎开发的移动游戏和移动VR游戏而言,内存的开销无外乎以下三大部分:1.资源内存占用;2.引擎模块自身内存占用;3.托管堆内存占用。
1.1 资源内存占用
在一个较为复杂的大中型项目中,资源的内存占用往往占据了总体内存的70%以上。因此,资源使用是否恰当直接决定了项目的内存占用情况。一般来说,一款游戏项目的资源主要可分为如下几种:纹理(Texture)、网格(Mesh)、动画片段(AnimationClip)、音频片段(AudioClip)、材质(Material)、着色器(Shader)、字体资源(Font)以及文本资源(Text Asset)等等。其中,纹理、网格、动画片段和音频片段则是最容易造成较大内存开销的资源。
1.2 引擎模块自身内存占用
引擎自身中存在内存开销的部分纷繁复杂,可以说是由巨量的“微小”内存所累积起来的,比如GameObject及其各种Component(最大量的Component应该算是Transform了)、ParticleSystem、MonoScript以及各种各样的模块。
一般情况下,上面所指出的引擎各组成部分的内存开销均比较小,真正占据较大内存开销的是这两处:WebStream和SerializedFile。其绝大部分的内存分配则是由AssetBundle加载资源所致。
1.3 托管堆内存占用
对于目前绝大多数基于Unity引擎开发的项目而言,其托管堆内存是由Mono分配和管理的。“托管” 的本意是Mono可以自动地改变堆的大小来适应你所需要的内存,并且适时地调用垃圾回收(Garbage Collection)操作来释放已经不需要的内存,从而降低开发人员在代码内存管理方面的门槛。
但是这并不意味着研发团队可以在代码中肆无忌惮地开辟托管堆内存,因为目前Unity所使用的Mono版本存在一个很严重的问题,即:Mono的堆内存一旦分配,就不会返还给系统。这意味着Mono的堆内存是只升不降的。
2.Unity内存意外浪费
2.1 内存泄露
2.2 无效的Mono堆内存开销
2.2.1 避免一次性堆内存的过大分配
2.2.2 避免不必要的堆内存开销
2.3 资源冗余
所谓“资源冗余”,是指在某一时刻内存中存在两份甚至多份同样的资源。导致这种情况的出现主要有两种原因:AssetBundle打包机制出现问题 和 资源的实例化所致。
3.Unity内存优化
3.1 把控资源的使用
3.1.1 严格控制资源大小和格式
3.1.2 避免使用一个资源占用多份内存空间
3.1.3 资源使用结束后判断是有需要及时释放
3.1.4 不常用的资源不放进内存
3.2 注意代码质量,避免申请大量的堆内存
3.2.1 善用对象池和资源缓存,避免频繁New()操作
3.2.2 资源使用完毕后切忌释放
3.2.3 string资源尽量复用。需要拼接时使用string.format()或者其他官方API。
3.2.4 避免在发布版本中频繁的输出日志
4.掌握UnityProfiler
死记硬背再多的优化方案,都不如掌握检测问题的方法!
在使用Profiler工具时,有一点需要大家特别注意:
我们在Editor中调试项目的时候发现纹理的内存大小是其本身大小的两倍,是因为Unity把内存和显存的大小都计算进去了吗?
参考资料: https://blog.uwa4d.com/archives/optimzation_memory_1.html
http://blog.csdn.net/cbbbc/article/details/51193588