簡介
AssetBundle(簡稱:AB包)?是 Unity 提供的一種資源壓縮包,用于在應用運行時動態地加載和卸載資源。它可以將非代碼資源(如模型、紋理、預制體、音頻、甚至整個場景)打包成一個或多個文件,這些文件可以存放在本地或遠程服務器上。(不支持打包C#腳本)
AB包的創建
AssetBundles Browser 打包工具
下載安裝
GitHub下載地址:GitHub - Unity-Technologies/AssetBundles-Browser: Editor tool for viewing and debugging asset bundle contents before and after builds
1、在Unity工程中創建文件夾Editor
2、將刪除資源包中Tests文件夾后放入到Editor文件夾中
3、確認是否安裝成功
打開Window=>AssetBundle Browser
資源打包
1、標記資源
選中資源,在Inspector面板進行Assetbundle標記。可以自定義包名和資源擴展名。AssetBundle的名字固定為小寫,如果在名字中使用了大寫字母,系統會自動轉換為小寫格式。另外,每個AssetBundle都可以設置一個擴展名。如果需要區別素材,可使用擴展名來加以區分。要添加子文件夾,請用 / 分隔文件夾名稱。例如,使用 AssetBundle 名稱 environment/forest 在 environment 子文件夾下創建名為 forest 的捆綁包。
2、資源設置
打開AssetBundle Browser窗口,可以看見已經標記過的AB包信息
3、了解Bulid面板
參數 | 描述 |
Build Target | 選擇面向什么平臺打包 |
Output Path | AssetBundle打包后的輸出路徑 |
Clear Folders | 指打包前是否將Output Path中的文件清空 |
Copy to StreamingAssets | 將Output path中的文件復制到Unity StreamingAssets文件夾中 |
Compression | No Compression 不壓縮,解壓快,但是AssetBundle包大 LZMA 壓縮大小最小,但是解壓慢,如果需要AB包中一個資源,會將所有資源進行解壓 LZ4 壓縮大小會比LZMA大,但是用什么資源就解壓什么資源(推薦) |
4、點擊Build按鈕,進行資源構建
每一個AssetBundle資源將會有一個和文件相關的“.mainfest”文件,該文件提供了所打包資源的CRC和資源依賴的信息。還有兩個文件(StandaloneWindows),記錄整個AssetBundle文件夾的信息,包括資源列表及各個列表之間的依賴關系。
自定義工具(使用AB包構建API)
輸出路徑一般情況下為Assets下的某一個文件夾,該文件夾不會自動創建,需要玩家在運行前手動創建,否則會報錯
[MenuItem("項目工具/AssetBundle/構建AB包資源")]
public static void BuildAssetBundleLogic()
{BuildPipeline.BuildAssetBundles("Assets/AssetBundles", BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows);
}
加載AB包
AssetBundle不能夠重復加載,否則報錯
方法 | 描述 |
AssetBundle.LoadFromFile | 從磁盤上的文件同步加載 AssetBundle。 |
AssetBundle.LoadAsset(string name) | 從捆綁包中加載名為 name 的資源。 |
AssetBundle.LoadAsset<T>(string name) | |
AssetBundle.LoadAsset(string name,Type type) | |
AssetBundle.LoadAllAssets | 加載AssetBundle中所有資源對象 |
AssetBundle.LoadAllAssetsAsync | 異步加載AssetBundle中所有資源togn |
為了便于測試,將打包后的AB包放到StreamingAssets文件夾中,實際開發時可以自己指定路徑。
同步加載
public Image icon;void Start()
{var abPath=Path.Combine(Application.streamingAssetsPath,"role.game");//先加載AB包var ab = AssetBundle.LoadFromFile(abPath);//從AB包中加載指定資源var sprite = ab.LoadAsset<Sprite>("迪希雅");icon.sprite = sprite;
}
異步加載
StartCoroutine(LoadABRes("role.game", "迪希雅", (obj) =>{if (obj is Sprite sprite){icon.sprite = sprite;}}));/// <summary>
/// 異步加載AB包中的資源
/// </summary>
/// <param name="abName">ab包名稱</param>
/// <param name="resName">資源名稱</param>
/// <param name="callback">成功加載后回調</param>
/// <returns></returns>
IEnumerator LoadABRes(string abName, string resName,Action<object> callback)
{//加載ab包var ab = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + abName);yield return ab;//從ab包中加載資源var asset = ab.assetBundle.LoadAssetAsync(resName, typeof(Sprite));yield return asset;callback?.Invoke(asset.asset);
}
卸載AB包
方法 | 描述 |
Unload (bool unloadAllLoadedObjects); 有異步方法 | 卸載 AssetBundle 釋放其數據。 當 unloadAllLoadedObjects 為 false 時,只卸載ab包,不清除已加載的資源 |
AssetBundle.UnloadAllAssetBundles(bool unloadAllObjects) 無異步方法 | 卸載當前已加載的所有 AssetBundle。 unloadAllObjects的true/false規則同上 |
private void UnloadAssetBundle(string abName)
{var list = AssetBundle.GetAllLoadedAssetBundles().ToList();for (var i = 0; i < list.Count; i++){var ab = list[i];if (ab.name == abName){ab.Unload(true);break;}}
}
注意
資源依賴問題
這是 AB 系統中最復雜也最容易出問題的部分。
如果包 A 中的預制體使用了包 B 中的材質,那么包 A 就依賴于包 B。加載包 A 中的預制體前,必須確保包 B 中的材質已經被加載到內存中。
//加載依賴資源
private void LoadDependRes(string abName)
{//加載主包var abMain = AssetBundle.LoadFromFile($"{Application.streamingAssetsPath}/StandaloneWindows");//加載主包中的固定文件var abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); //從固定文件中,得到依賴信息var strs = abManifest.GetAllDependencies(abName);//得到了依賴包的名字foreach (var item in strs){AssetBundle.LoadFromFile($"{Application.streamingAssetsPath}/{item}");}
}