看了两篇关于Unity加载和内存管理的文章,写得很详细。
文章链接:
http://game.ceeger.com/forum/read.php?tid=4394
http://game.ceeger.com/forum/read.php?tid=4466
Unity系统在加载新场景时,所有的内存对象都会被自动销毁,包括你用AssetBundle.Load加载的对象和Instaniate克隆的。
但是不包括AssetBundle文件自身的内存镜像,那个必须要用Unload来释放,用.net的术语,这种数据缓存是非托管的。
既然加载场景不会释放AssetBundle文件自身的内存镜像,那我们就手动释放。
Destroy:主要用于销毁克隆对象,也可以用于场景内的静态物体,不会自动释放该对象的所有引用。虽然也可以用于Asset,但是概念不一样要小心,如果用于销毁从文件加载的Asset对象会销毁相应的资源文件!但是如果销毁的Asset是Copy的或者用脚本动态生成的,只会销毁内存对象。
AssetBundle.Unloadfalse):释放AssetBundle文件内存镜像
AssetBundle.Unloadtrue):释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存对象
Reources.UnloadAssetObject):显式的释放已加载的Asset对象,只能卸载磁盘文件加载的Asset对象
Resources.UnloadUnusedAssets:用于释放所有没有引用的Asset对象
GC.Collect)强制垃圾收集器立即释放内存 Unity的GC功能不算好,没把握的时候就强制调用一下
场景A切换到场景B,使用同步加载Application.LoadLevelsceneName)或者异步加载Application.LoadLevelAsyncsceneName)都可以。
我们可以在场景A和场景B之间插入一个清理内存的场景X,场景X就是一个空场景,它的主要作用是承上启下,把场景A留下的资源清理,然在切换到场景B。
可以这个功能封装起来。
1 using System; 2 using UnityEngine; 3 using System.Collections; 4 using System.Runtime.CompilerServices; 5 using Object = UnityEngine.Object; 6 7 public class ClearSceneData : MonoBehaviour 8 { 9 //异步对象 10 private AsyncOperation async; 11 12 //下一个场景的名称 13 private static string nextSceneName; 14 15 void Awake) 16 { 17 Object[] objAry = Resources.FindObjectsOfTypeAll<Material>); 18 19 for int i = 0; i < objAry.Length; ++i) 20 { 21 objAry[i] = null;//解除资源的引用 22 } 23 24 Object[] objAry2 = Resources.FindObjectsOfTypeAll<Texture>); 25 26 for int i = 0; i < objAry2.Length; ++i) 27 { 28 objAry2[i] = null; 29 } 30 31 //卸载没有被引用的资源 32 Resources.UnloadUnusedAssets); 33 34 //立即进行垃圾回收 35 GC.Collect); 36 GC.WaitForPendingFinalizers);//挂起当前线程,直到处理终结器队列的线程清空该队列为止 37 GC.Collect); 38 39 } 40 41 void Start) 42 { 43 StartCoroutine"AsyncLoadScene", nextSceneName); 44 } 45 46 /// <summary> 47 /// 静态方法,直接切换到ClearScene,此脚本是挂在ClearScene场景下的,就会实例化,执行资源回收 48 /// </summary> 49 /// <param name="_nextSceneName"></param> 50 public static void LoadLevelstring _nextSceneName) 51 { 52 nextSceneName = _nextSceneName; 53 Application.LoadLevel"ClearScene"); 54 } 55 56 /// <summary> 57 /// 异步加载下一个场景 58 /// </summary> 59 /// <param name="sceneName"></param> 60 /// <returns></returns> 61 IEnumerator AsyncLoadScenestring sceneName) 62 { 63 async = Application.LoadLevelAsyncsceneName); 64 yield return async; 65 } 66 67 void OnDestroy) 68 { 69 async = null; 70 } 71 72 }
