Unity 3D 資源的載入與釋放
阿新 • • 發佈:2019-01-05
版本:unity 5.4.1 語言:C#
海水先在這裡坑一會,看了裡面的演算法深深感到自己數學能力的不足,經過同學的推薦,我準備先看會《數值分析》閉關修煉一下。
至於我在看的實戰核心技術的第十章MVC設計框架,提供了一堆無用的程式碼,然後讓你去看他的課程,我就自己研究一下如何從Asset中載入到場景中,又如何在場景中釋放資源。
總結一下網上一共有三種方法(這次最終解決了AssetBundle的載入問題,AssetBundle原來是要打包後才能載入……):靜態載入、Resources.Load、AssetBundle.LoadAsset。
各有不同的用處吧,本地的話前兩個更加容易管理使用,
接下來看程式碼:
(參考:http://www.taidous.com/portal.php?mod=view&aid=445&page=1)
public class ResManager : MonoBehaviour { public GameObject tps; void Start () { //StartCoroutine(LoadResByResources("TPS")); //StartCoroutine(LoadResByStatic()); StartCoroutine(LoadResByBundle("file://" + Application.dataPath + @"/Resources/rs.assetbundle", "assets/standard assets/characters/thirdpersoncharacter/prefabs/thirdpersoncontroller.prefab")); } // Resources的方法載入資源,只能在Resources資料夾下讀取,不想建立Resources資料夾的可以考慮靜態載入 IEnumerator LoadResByResources(string path) { Resources.UnloadUnusedAssets(); // 讀取,此時僅讀取了資源的少量資訊,並不佔多少記憶體 GameObject go = Resources.Load<GameObject>(path); yield return new WaitForSeconds(5f); // 建立,如果Instantiate過多會產生卡頓,所以在載入大量資源的時候,考慮物件池 // 先在讀取進度的時候把物件創建出來,並SetActive(false),使用的時候SetActive(true) GameObject goInit = Instantiate(go); goInit.transform.parent = transform; goInit.transform.localPosition = Vector3.zero; goInit.transform.localRotation = Quaternion.identity; yield return new WaitForSeconds(5f); // 銷燬物件,但各種資源還佔據記憶體 Destroy(goInit); yield return new WaitForSeconds(5f); // 解除安裝所有沒有引用的資源,相當於清空了記憶體 // 但最好不要主動使用,轉換場景的時候會清空資源 Resources.UnloadUnusedAssets(); } // 靜態的方法載入資源,效果與Resources載入類似 IEnumerator LoadResByStatic() { Resources.UnloadUnusedAssets(); yield return new WaitForSeconds(5f); GameObject goInit = Instantiate(tps); goInit.transform.parent = transform; goInit.transform.localPosition = Vector3.zero; goInit.transform.localRotation = Quaternion.identity; yield return new WaitForSeconds(5f); Destroy(goInit); yield return new WaitForSeconds(5f); Resources.UnloadUnusedAssets(); } // 使用AssetBundle載入資源,在LoadAsset的時候就會載入大量的資源 // 所以例項化時載入的資源量反而小,可以考慮利用這種方法做載入而不卡頓 IEnumerator LoadResByBundle(string path, string name) { Resources.UnloadUnusedAssets(); // 建立WWW讀取,這邊是本地 WWW bundle = new WWW(path); yield return bundle; yield return new WaitForSeconds(5f); // 從讀取到的資源中獲取對應prefab //Object obj = bundle.assetBundle.Load(name); //方法已經被廢棄 Object obj = bundle.assetBundle.LoadAsset(name); yield return new WaitForSeconds(5f); // 例項化 GameObject goInit = Instantiate(obj) as GameObject; goInit.transform.parent = transform; goInit.transform.localPosition = Vector3.zero; goInit.transform.localRotation = Quaternion.identity; yield return new WaitForSeconds(5f); // 刪除 Destroy(goInit); yield return new WaitForSeconds(5f); // Unload釋放記憶體映象,引數是是否強制刪除記憶體資源 // true強制刪除,即使記憶體有引用也刪除 //bundle.assetBundle.Unload(true); // 刪除沒有引用的資源,比如說這邊,如果呼叫的是這個方法的的話 // 雖然資源已經被刪除了,但記憶體中還保留的該prefab,直到呼叫Resources.UnloadUnusedAssets() bundle.assetBundle.Unload(false); Resources.UnloadUnusedAssets(); } // 打包方法是jiange啊啊啊撰寫的(http://blog.csdn.net/janeky/article/details/17652021) // 這個方法是打包當前專案的資源,從而形成assetbundle檔案,供LoadResByBundle載入 [MenuItem("Assets/Build AssetBundle From Selection")] static void ExportResourceRGB2() { // 開啟儲存面板,獲得使用者選擇的路徑 string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "assetbundle"); if (path.Length != 0) { // 選擇的要儲存的物件 Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets); //打包 BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, BuildTarget.StandaloneWindows); } } }
靜態讀取和Resources.Load最好先把要用到的例項出來,嗯,在進度讀取的時候做,然後SetActive(false)將其隱藏,這樣卡頓現象應該不會出現吧。
好了,這本書我看了,再寫個熱更新吧,其他章節也沒什麼好看的了。