- 内存部分
- 理解托管堆 【推荐阅读】
5.1
5.2 - 字符串和文本
- 资源目录
- 通用的优化方案
- 一些特殊的优化方案
内存消耗是关键的性能指标,尤其对于在内存资源非常有限的设备上,如移动设备。
剖析内存消耗
注意,这个工具在Unity5.3之后的版本都可以使用,如果应用是用IL2CPP打包的,它可以提取原生代码和托管代码的内存消耗信息。
使用这个工具,需要使用IL2CPP工具进行打包并且发布到合适的设备上,然后连接上编辑器中的CPU剖析工具,打开内存剖析界面(Window > MemoryProfilerWindow)选择Take Snapshot。
设备上收集数据,并将这些数据发送给Unity编辑器,应用会暂停一段时间。然后Unity编辑器开始分析数据,这也需要比较久的时间。对于内存比较敏感的应用,这个过程可能需要10-30分钟完成。
在解析数据和加载的过程中,建议各位耐心等待。
image.png上面的截图来自于iOS设备上运行的标准Asset场景,显示了四分之三多的内存给了四个非常大的飞行器的机身纹理贴图。
这个可视化的工具也可以被放大。点击每个方块可以获得更多的相关信息。
定位重复的纹理
最常见的内存问题是在内存中的资源重复。纹理是最占内存开销的资源类型,纹理重复是Unity项目中最常见的问题。
如果两个对象是相同大小,相同类型,那么很有可能这两个对象是从同一个Asset加载进来的。在新的内存剖析器中,可以通过Name和InstanceID观察查看资源。
Name是加载进来的Asset文件的名称,通常不带路径名和后缀。InstanceID是Unity采用的内部识别编号,在Unity运行的过程中,这个编号是独一无二的。
image.png这张图示范了资源重复的一个例子。图形的左边和右边是从Unity5.4的内存剖析器中的某个细节面板。两张图的Asset实际上是内存中两个分开加载的纹理资源,名字和大小相同。可以在Assets目录下搜索资源名字,确认是否只有一个资源较这个名字,从而确定是不是资源重复加载。
内存中每个独立的UnityEngine.Object都有独特的instance ID,当Object被创建的时候指定。这两个纹理有不同的Instance IDs,所以它们代表了两份不同的纹理数据。
因为Asset的大小和名称相同,而InstanceID不同,所以可以确定一个纹理被加载了两次。虽然有可能会出现两个同名的资源文件,所以还是按照文件大小来判定。
AssetBundle和Asset重复
纹理资源和Asset重复的最大原因是AssetBundle的不合理使用。可以参见AssetBundle相关的知道。关键章节是管理已经加载的Asset。
检查图片缓冲区,图片效果和RenderTexture内存使用
同样也可以在剖析器中看到为图片效果和RenderTexture提供渲染缓冲区占用的内存大小。
image.png上面的截图展示了使用了Unity电影图片效果的一个场景的内存剖析器的情况。这个图片效果分配了临时渲染缓冲区,而且Bloom效果分配了多个缓冲区。因为iOS设备的高分辨率,这些临时缓冲区占用了非常多的内存,比项目中剩下的占用的总数还多。
考虑到iPad Air2的分辨率是2048x1536,比大部分终端设备和PC的1080p的分辨率高出了很多。全屏的临时渲染缓冲区差不多消耗24MB~36MB,取决于缓冲区的格式。降低渲染缓冲区的像素大小可以节省75%的内存消耗,同时也不会对最终的效果造成很大的影响。
如果觉得文章对您有用,请点个赞呗!☺☺☺