标签:
最近unity 当需要频繁创建一个物体对象时,怎样减少内存. 这里写下关于Unity3D对于内存的管理与优化.
详细说一下细节概念:
AssetBundle运行时加载:
Assets加载:
用AssetBundle.Load(同Resources.Load) 这才会从AssetBundle的内存镜像里读取并创建一个Asset对象,创建Asset对象同时也会分配相应内存用于存放(反序列化)
AssetBundle的释放:
AssetBundle.Unload(flase)是释放AssetBundle文件的内存镜像,不包含Load创建的Asset内存对象。你 Instaniate一个Prefab,是一个对Assets进行Clone(复制)+引用结合的过程,GameObject transform 是Clone是新生成的。其他mesh / texture / material / shader 等,这其中些是纯引用的关系的,包括:Texture和TerrainData,还有引用和复制同时存在的,包括:Mesh/material /PhysicMaterial。引用的Asset对象不会被复制,只是一个简单的指针指向已经Load的Asset对象。这种含糊的引用加克隆的混合, 大概是搞糊涂大多数人的主要原因。
Unity3D占用内存太大怎么解决呢?
虽然都叫Asset,但复制的和引用的是不一样的,这点被Unity的暗黑技术细节掩盖了,需要自己去理解。
关于内存管理
按照传统的编程思维,最好的方法是:自己维护所有对象,用一个Queue来保存所有object,不用时该Destory的,该Unload的自己处理。
创建时:
先建立一个AssetBundle,无论是从www还是文件还是memory如果需要立即释放内存加上GC.Collect(),否则内存未必会立即被释放,有时候可能导致内存占用过多而引发异常。
这样可以保证内存始终被及时释放,占用量最少。也不需要对每个加载的对象进行引用。
当然这并不是唯一的方法,只要遵循加载和释放的原理,任何做法都是可以的。
总结一下各种加载和初始化的用法:
AssetBundle.CreateFrom.....:创建一个AssetBundle内存镜像,注意同一个assetBundle文件在没有Unload之前不能再次被使用
总结一下各种释放
Destroy: 主要用于销毁克隆对象,也可以用于场景内的静态物体,不会自动释放该对象的所有引用。虽然也可以用于Asset,但是概念不一样要小心,如果用于销毁从文 件加载的Asset对象会销毁相应的资源文件!但是如果销毁的Asset是Copy的或者用脚本动态生成的,只会销毁内存对象。
举两个例子帮助理解
例子1:
其实存在3种加载方式:
一是静态引用,建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate
例子2:
从磁盘读取一个1.unity3d文件到内存并建立一个AssetBundle1对象Texture是引用对象,永远不会有自动复制的情况出现(除非你真需要,用代码自己实现copy),只会是
创建和添加引用
如果继续:
创建时:
先建立一个AssetBundle,无论是从www还是文件还是memory
销毁时:
对Instantiate的对象进行Destroy
几种AssetBundle创建方式的差异:
CreateFromFile:这种方式不会把整个硬盘AssetBundle文件都加载到 内存来,而是类似建立一个文件操作句柄和缓冲区,需要时才实时Load,所以这种加载方式是最节省资源的,基本上AssetBundle本身不占什么内 存,只需要Asset对象的内存。可惜只能在PC/Mac Standalone程序中使用。
看一个例子:
Object obj = Resources.Load("MyPrefab");
这时候:
obj = null;Unity3D占用内存太大怎么解决呢?
图片:p12.jpg标签:
原文地址:http://my.oschina.net/u/185335/blog/379929