1. 程式人生 > >Unity3d之AssetBundle打包與讀取

Unity3d之AssetBundle打包與讀取

一、建立Assetbundle

Unity3D開發的遊戲中,無論模型,音訊,還是圖片等,我們都做成Prefab,然後打包成Assetbundle,方便我們後面的使用,來達到資源的更新。

       一個Assetbundle可以打包一個模型(這裡的模型不單單指的是預製模型,可以是Project檢視下的任何東西),也可以是多個模型,但兩種打包方式佔用的空間不一樣。

      比如我打包三個一樣的模型(只不過他們的指令碼不一樣建立三個空的GameObject(One,Two,Three),分別掛載指令碼One,Two,Three)。如果我為每個模型單獨打包生成One,Two,Three三個Assetbundle,其所佔的空間是A,B,C,但是A+B+C != D.由此可知想通的資源儘可能的打包到一起,他們共用一套資源。不相同的模型儘量分開打包。



二、分開打包(注意這個指令碼必須放在Editor資料夾內,Editor資料夾沒有的話需自己建立)

[csharp] view plain copy print?
  1. /// <summary>
  2. /// 將選中的預製分別打包
  3. /// </summary>
  4. [MenuItem("AssetBundleDemo/Create AssetBundles By themselves")]  
  5. staticvoid CreateAssetBundleThemelves(){  
  6.     //獲取要打包的物件(在Project檢視中)
  7.     Object[] selects = Selection.GetFiltered (typeof
    (Object),SelectionMode.DeepAssets);  
  8.     //遍歷選中的物件
  9.     foreach(Object obj in selects){  
  10.         //這裡建立一個本地測試
  11.         //注意本地測試中可以是任意的檔案,但是到了移動平臺只能讀取路徑StreamingAssets裡面的
  12.         //StreamingAssets是隻讀路徑,不能寫入
  13.         string targetPath = Application.dataPath + "/AssetBundleLearn/StreamingAssets/" + obj.name + ".assetbundle"
    ;//檔案的字尾名是assetbundle和unity都可以
  14.         if(BuildPipeline.BuildAssetBundle(obj,null,targetPath,BuildAssetBundleOptions.CollectDependencies)){  
  15.             Debug.Log(obj.name + "is packed successfully!");  
  16.         }else{  
  17.             Debug.Log(obj.name + "is packed failly!");  
  18.         }  
  19.     }  
  20.     //重新整理編輯器(不寫的話要手動重新整理,否則打包的資源不能及時在Project檢視內顯示)
  21.     AssetDatabase.Refresh ();  
  22. }  

SelectionMode.DeepAssets

這個選擇模式意味著如果選擇中包含多個檔案,那麼他將包含這個檔案檢視中的所有資源。

他還有其他的各種選項(以下是官方文件)

SelectionMode

Description

SelectionMode can be used to tweak the selection returned by Selection.GetTransforms.

The default transform selection mode is: SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable.

Return the whole selection.
Only return the topmost selected transform. A selected child of another selected transform will be filtered out.
DeepReturn the selection and all child transforms of the selection.
Excludes any prefabs from the selection.
Excludes any objects which shall not be modified.
Only return objects that are assets in the Asset directory.
If the selection contains folders, also include all assets and subfolders within that folder in the file hierarchy.

最核心的方法:BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies)

引數1:它只能放一個物件,因為我們這裡是分別打包,所以通過迴圈將每個物件分別放在了這裡。

引數2:可以放入一個數組物件。

引數3:要打包到的路徑

引數4:預設情況下打的包只能在電腦上用,如果要在手機上用就要新增一個引數。

BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.android)

iOS上:

BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.iPhone)

另外,電腦上和手機上打出來的Assetbundle不能混用,不同平臺只能用自己的。

三、一起打包[csharp] view plain copy print?
  1. /// <summary>
  2. /// 將選中的預製打包到一起
  3. /// </summary>
  4. [MenuItem("AssetBundleDemo/Create AssetBundles Together")]  
  5. staticvoid CreateAssetBundleTogether(){  
  6.     //要打包的物件
  7.     Object[] selects = Selection.GetFiltered (typeof(Object),SelectionMode.DeepAssets);  
  8.     //要打包到的路徑
  9.     string targetPath = Application.dataPath + "/AssetBundleLearn/StreamingAssets/Together.assetbundle";  
  10.     if(BuildPipeline.BuildAssetBundle(null,selects,targetPath,BuildAssetBundleOptions.CollectDependencies)){  
  11.         Debug.Log("Packed successfully!");  
  12.     }else{  
  13.         Debug.Log("Packed failly!");  
  14.     }  
  15.     //重新整理編輯器(不寫的話要手動重新整理)
  16.     AssetDatabase.Refresh ();  
  17. }  


四、讀取

[csharp] view plain copy print?
  1. using UnityEngine;  
  2. using System.Collections;  
  3. publicclass ReanAssetbundle : MonoBehaviour {  
  4.     //不同平臺下StreamingAssets的路徑是不同的,這裡需要注意一下。
  5.     publicstaticreadonlystring m_PathURL =  
  6.         #if UNITY_ANDROID
  7.         "jar:file://" + Application.dataPath + "!/assets/";  
  8.         #elif UNITY_IPHONE
  9.         Application.dataPath + "/Raw/";  
  10.         #elif UNITY_STANDALONE_WIN || UNITY_EDITOR
  11.         "file://" + Application.dataPath + "/AssetBundleLearn/StreamingAssets/";  
  12.         #else
  13.         string.Empty;  
  14.         #endif
  15.     void OnGUI(){  
  16.         if(GUILayout.Button("載入分開打包的Assetbundle")){  
  17.             StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "One.assetbundle"));  
  18.             StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL +  "Two.assetbundle"));  
  19.             StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "Three.assetbundle"));  
  20.         }  
  21.         if(GUILayout.Button("載入打包在一起的Assetbundle")){  
  22.             StartCoroutine(LoadGameObjectPackedTogether(m_PathURL + "Together.assetbundle"));  
  23.         }  
  24.     }  
  25.     //單獨讀取資源
  26.     private IEnumerator LoadGameObjectPackedByThemselves(string path){  
  27.         WWW bundle = new WWW (path);  
  28.         yield return bundle;  
  29.         //載入
  30.         yield return Instantiate (bundle.assetBundle.mainAsset);  
  31.         bundle.assetBundle.Unload (false);  
  32.     }  
  33.     IEnumerator  LoadGameObjectPackedTogether (string path)  
  34.     {  
  35.         WWW bundle = new WWW (path);  
  36.         yield return bundle;  
  37.         Object one = bundle.assetBundle.Load ("One");  
  38.         Object two = bundle.assetBundle.Load ("Two");  
  39.         Object three = bundle.assetBundle.Load ("Three");  
  40.         //載入
  41.         yield return Instantiate (one);  
  42.         yield return Instantiate (two);  
  43.         yield return Instantiate (three);  
  44.         bundle.assetBundle.Unload (false);  
  45.     }  
  46. }  

推薦一個視覺化打包工具,寫了個詳細的說明,而且可以簡單實現資源的複用,避免重複打包