Unity在場景切換之間清理下內存


看了兩篇關於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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM