AssetBundle 加載、使用以及卸載


1.本地異步

 1  IEnumerator LoadFromMemoryAsync(string path)
 2 
 3     {
 4 
 5         AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
 6 
 7         yield return createRequest;
 8 
 9         AssetBundle bundle = createRequest.assetBundle;
10 
11         var prefab = bundle.LoadAsset<GameObject>("MyObject");
12         Instantiate(prefab);
13 
14     }

2.本地同步(同步會造成主線程的卡頓,造成游戲畫面的不流暢)

 1 public class LoadFromFileExample extends MonoBehaviour {
 2     function Start() {
 3         var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
 4         if (myLoadedAssetBundle == null) {
 5             Debug.Log("Failed to load AssetBundle!");
 6             return;
 7         }
 8         var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("MyObject");
 9         Instantiate(prefab);
10     }
11 }

 

 

3.從web端下載並加載 (要引用UnityEngine.Networking命名空間)

IEnumerator IE_LoadAssetBundleByName(string bundleName)
    {
        
        while (!Caching.ready)
        {
            yield return null;
        }
        string fileType;
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
        fileType = "file://";

#elif UNITY_ANDROID && !UNITY_EDITOR
        fileType = "jar://";
#endif

        UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(fileType + assetBundlePath + "/" , 0);

        yield return request.SendWebRequest();//開始請求
        while (!request.isDone)
        {
            Debug.Log("正在下載:" + request.downloadProgress.ToString());
            yield return 1;
        }

        if (request.isDone)
        {
            Debug.Log("完成");
        }
        if (request.isNetworkError || request.isHttpError)
        {
            Debug.Log("錯誤");
        }
        else//完成
        {
            Debug.Log("完成可用");
            AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
       //完成以后就能用了
            if (ab == null)
            {
                yield break;
            }

            
        }

        request.Dispose();
    }

 

 

加載好的AssetBundle使用以下這段代碼

 1 T objectFromBundle = bundleObject.LoadAsset<T>(assetName); 

T是要加載的資源類型。

決定如何加載資源時有幾個選項。我們有LoadAssetLoadAllAssets和他們同行的異步LoadAssetAsyncLoadAllAssetsAsync分別。

這是如何同步從AssetBundles加載資源:

要加載單個GameObject:

 1 GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName); 

要加載所有資源:

 1 Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets(); 

異步加載資源,在訪問資產之前,您需要等待此操作完成。

單個資源:

AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync<GameObject>(assetName);
yield return request;
var loadedAsset = request.asset;

 

所有資源:

AssetBundleRequest request = loadedAssetBundle.LoadAllAssetsAsync();
yield return request;
var loadedAssets = request.allAssets;

 

但是,為了節省空間,我們在打包AssetBundle包的時候經常把多個資源的依賴項單獨打包。比如說有兩個模型modelA和modelB,他們共同使用了matA的材質球,這個matA就是modelA和modelB的依賴項,如果我們只加載modelA或者modelB,那么這兩個模型的材質是丟失的。所以為了避免這個情況,我們要根據依賴文件來先找到依賴項並加載它(bundle包)。

加載依賴文件:

 1 private void GetAssetBundleManifest(string path)
 2     {
 3         AssetBundle maniFestAb = AssetBundle.LoadFromFile(path + "/AssetBundles");
 4         if (maniFestAb == null)
 5         {
 6             Debug.Log("加載失敗");
 7             return;
 8         }
 9         AssetBundleManifest manifest = maniFestAb.LoadAsset<AssetBundleManifest>("AssetBundleManifest");//AssetBundleManifest基本固定的,不用改
10 
11         string[] strArrAllAb = manifest.GetAllAssetBundles();//獲取所有包的包名(就是我們打包時候取的名字,連帶了路徑)
12 
13         for (int i = 0; i < strArrAllAb.Length; i++)
14         {
15             //做你想做的事,推薦放到字典里,以后想加載的時候查找一次(廢話)
16         }
17         AssetBundle.UnloadAllAssetBundles(true);//如果用不到了記得卸載資源,把我們要的信息放個一個字典里就好,只加載一次(再次廢話)。
18     }

 

好了,我們雖然加載了資源,但是assetbundle包其實還留在內存中。這時候,為了節約性能,我們要把不用的資源刪除。

可以使用這個: AssetBundle.Unload(bool) 

參數區別:

a. 參數是true的時候是完全卸載資源,包括了AB包(AssetBundle,一下都簡稱AB包,每次都打太麻煩了)和實例化的資源。就算是正在引用的資源也會被卸載,如果使用不當,會造成紋理丟失之類的情況。應該確保資源確實沒有哪里引用了,才調用AssetBundle.Unload(true);

b. 參數是false的時候會卸載所有沒有被引用的資源,這就造成了源AB包已經被卸載,實例化出來、並被人使用者的某資源就沒有了標記,再次加載這個物體的時候要重新加載ab包,加載你要的某資源,之前加載的某資源雖然沒有用了,但是還存在於游戲內存中,這樣下去就會越積越多,就炸了。

所以要調用一下  Resources.UnloadUnusedAssets(); 這個方法。另外,在游戲場景切換的時候,引擎也會自動的調用這個方法,把不存在引用的資源卸載。

 


免責聲明!

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



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