Unity在場景切換之間清理下記憶體
Unity系統在載入新場景時,所有的記憶體物件都會被自動銷燬,包括你用AssetBundle.Load載入的物件和Instaniate克隆的。
但是不包括AssetBundle檔案自身的記憶體映象,那個必須要用Unload來釋放,用.net的術語,這種資料快取是非託管的。
既然載入場景不會釋放AssetBundle檔案自身的記憶體映象,那我們就手動釋放。
Destroy:主要用於銷燬克隆物件,也可以用於場景內的靜態物體,不會自動釋放該物件的所有引用。雖然也可以用於Asset,但是概念不一樣要小心,如果用於銷燬從檔案載入的Asset物件會銷燬相應的資原始檔!但是如果銷燬的Asset是Copy的或者用指令碼動態生成的,只會銷燬記憶體物件。
AssetBundle.Unload(false):釋放AssetBundle檔案記憶體映象
AssetBundle.Unload(true):釋放AssetBundle檔案記憶體映象同時銷燬所有已經Load的Assets記憶體物件
Reources.UnloadAsset(Object):顯式的釋放已載入的Asset物件,只能解除安裝磁碟檔案載入的Asset物件
Resources.UnloadUnusedAssets:用於釋放所有沒有引用的Asset物件
GC.Collect()強制垃圾收集器立即釋放記憶體 Unity的GC功能不算好,沒把握的時候就強制呼叫一下
場景A切換到場景B,使用同步載入Application.LoadLevel(sceneName)或者非同步載入Application.LoadLevelAsync(sceneName)都可以。
我們可以在場景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 LoadLevel(string _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 AsyncLoadScene(string sceneName) 62 { 63 async = Application.LoadLevelAsync(sceneName); 64 yield return async; 65 } 66 67 void OnDestroy() 68 { 69 async = null; 70 } 71 72 }