簡單總結AssetBundle的打包/解包
阿新 • • 發佈:2019-01-30
最近參考了各位大神的資源,初步學習了Unity的資源管理模式,包括在編輯器管理(使用AssetDatabase)和在執行時管理(使用Resources和AssetBundle)。在此簡單總結執行時用AssetBundle動態打包/解包資源的方法,方便自己回顧。
關於AssetBundle有很多的細節問題,在此先作個筆記,等更多的問題搞清楚了/有了新的理解,再接著補充/修改。
建立編輯器選單項,用於打包AssetBundle
using UnityEngine;
using System.Collections;
using System.Collections.Generic; // 需要使用List集合
using UnityEditor; // 建立編輯器選單項需要匯入這個檔案
public class CreateMenuItem { // 不需要繼承Mono
[MenuItem("My MenuItem/Build AssetBundle")]
public static void BuildBundle()
{
List<AssetBundleBuild> list = new List<AssetBundleBuild>(); // 多個資源可以打入一個包中,不確定個數時,可用List集合一個一個新增
AssetBundleBuild b = new AssetBundleBuild();
b.assetBundleName = "1.unity3d"; // 用於載入該資源,相當於這個資源在AssetBundleBuild中的ID,因為AssetBundleBuild中可能有多個資源
b.assetNames = new string[] { "Assets/Resources/Images/1.jpg" }; // 這個AssetBundleBuild裡包含的哪些資源
list.Add(b);
// 該方法不會自動生成資料夾,所以若指定的資料夾不存在,則打包失敗
BuildPipeline.BuildAssetBundles("Assets/Bundles" , list.ToArray(), BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}
}
打包成功後,在目標資料夾下多瞭如下4個檔案:
關於製作編輯器選單項
- 需要把該指令碼放在Editor目錄下,建議在Assets根目錄下新建“Editor”資料夾。
- 需要匯入UnityEditor檔案。
- 選單項的類不用繼承MonoBehaviour。
- 點選選單項觸發的函式是static靜態的。
關於打包AssetBundle
- assetBundleName : 該資源打入包後的名字,解包時可用該名字訪問到該資源。
- assetNames : 要被打包的資源當前的相對路徑。
- 打包函式:BuildPipeline.BuildAssetBundles()。
- 打包函式要求傳入AssetBundleBuild[]陣列,因為一個AssetBundle壓縮包中可以被加入多個資源,可以使用動態陣列List來替代(不用指定陣列長度),使用集合的Add()方法將資源一個一個加入包中。
- 關於引數BuildAssetBundleOptions,以前常用的選項BuildAssetBundleOptions.CollectDependencies和BuildAssetBundleOptions.CompleteAssets都已過時,官方文件解釋是這兩種選項現在都預設會被執行。關於這個引數我沒有過多的探究,這裡暫時選用了BuildAssetBundleOptions.None。
- 方法的最後一個引數BuildTarget指定打包到哪個平臺下,這裡我用PC測試選擇BuildTarget.StandaloneWindows64。
- 打包方法中填的目標資料夾路徑如果不存在,該方法不會建立該資料夾,打包失敗。
- 這裡只是簡單的打包一個資源,沒有涉及打包多個資源時,不同資源有共通引用別的資源的問題,學習中。
載入/解包AssetBundle
public class LoadAssetBundle : MonoBehaviour {
void Start () {
StartCoroutine(Load());
}
// 載入AssetBundle壓縮包是個非同步過程,需要開啟協程
IEnumerator Load()
{
// 步驟一:獲取AssetBundle壓縮包
// WWW www = new WWW("http://myserver/myBundle.unity3d"); // 從遠端伺服器下載
// WWW www = new WWW("File://" + Application.streamingAssetsPath + "1.unity3d"); // 手機上從本機載入
WWW www = new WWW("File:///D:/Unity Projects/Learn Asset Manage/Assets/Bundles/1.unity3d"); // 從PC本機載入,是三個槓
yield return www;
AssetBundle build = www.assetBundle;
Debug.Log(build); // 測試是否非空
// 步驟二:解包獲取資源
/*
// 非同步載入,分幀操作
AssetBundleRequest request = build.LoadAssetAsync("Assets/Prefabs/airplane.prefab", typeof(GameObject)); // 名字和型別是打包時確定的
yield return request;
GameObject go = request.asset as GameObject;
*/
// 同步載入,速度更快,但可能會阻塞主執行緒
GameObject go = build.LoadAsset<GameObject>("Assets/Prefabs/airplane.prefab");
Instantiate(go, new Vector3(0, 0, 0), Quaternion.identity);
// 完成後釋放原始映象檔案
www.Dispose();
}
}
注意點:
- 載入AssetBundle壓縮包是個非同步過程,需要開啟協程。
- 壓縮包的獲取方式有三種:從遠端伺服器、手機上本地載入、PC上本地載入。想要在手機上載入本地AssetBundle,需要將所需資源包存放在自建立的名為“StreamingAssets”的資料夾中,該資源才能釋出到真機上。參考Streaming Assets
- 解AssetBundle包可以使用非同步或同步載入方式,前者分幀操作載入稍慢,後者載入更快但可能阻塞主執行緒。
- 解壓完成後可以通過www.Dispose()方法將原WWW的壓縮包映象檔案釋放。