1前言

Unity在5.0中推出了新的AssetBundle管理機(jī)制,本文將對此進(jìn)行介紹并完成簡單實(shí)踐。
2什么是AssetBundles?
AssetBundles是一堆從你的Unity項(xiàng)目中導(dǎo)出的文件,這些文件以特殊的格式組織,并能夠在你的項(xiàng)目中按需加載。AssetBundles通過后綴名支持所有Unity支持的文件類型。如果你想包含一些自定義的二進(jìn)制數(shù)據(jù),可以將使用.bytes作為后綴。Unity在導(dǎo)入時將把此類文件當(dāng)作一個TextAsset。
3工作流
3.1創(chuàng)建
開發(fā)階段,開發(fā)者將AssetBundles上傳至至服務(wù)器

這就有兩個階段:
3.1.1你需要通過編輯器構(gòu)建AssetBundles。
3.1.2上傳至服務(wù)器。
3.2使用
程序運(yùn)行階段,客戶端從服務(wù)器下載AssetBundles,并按需操作每個AssetBundle中的資源。

即如下兩個階段:
3.2.1客戶端運(yùn)行時下載AssetBundles。
3.2.2從AssetBundles中加載對象。
4實(shí)踐
4.1構(gòu)建AssetBundles
4.1.1準(zhǔn)備工作
我們事先準(zhǔn)備一些簡單的資源:
簡單的創(chuàng)建兩個矩形,兩個球形。

選中一個Cube,在Inspector視口中的下方,有一個預(yù)覽窗口。在預(yù)覽窗口中,我們可以新建并指定資源將被打包進(jìn)的AssetBundle(默認(rèn)是None,這表示該資源不被打包進(jìn)任何AssetBundle,而是被打包進(jìn)主工程本身),如圖:

圖中有兩個下拉框,左邊的用于指定AssetBundle的名字,后邊的用于指定AssetBundle Variants的名字(后文介紹)。
我們新建一個名為shape/cube的AssetBundle,將兩個Cube資源指定到其中。新建一個名為shape/sphere的AssetBundle,將兩個Sphere資源指定其中(對應(yīng)的meta文件也將被指定到該AssetBundle)。AssetBundle的命名必須小寫(即便寫成大寫也會被轉(zhuǎn)換成小寫),并且支持'/',這樣可以在界面上開辟子目錄。如圖:

如果你創(chuàng)建了一些沒有指定任何資源的AssetBundle,Remove Unused Names 按鈕可以將其全部清除。
4.1.2導(dǎo)出AssetBundle
我們在項(xiàng)目中新建Editor文件夾,并在其中創(chuàng)建一個腳本:
BuildAssetBungle.cs
using UnityEditor;
public class BuildAssetBundle
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
BuildPipeline.BuildAssetBundles("Assets/MyAssetBundles");
}
}
這樣在菜單欄中,就會創(chuàng)建對應(yīng)的按鈕讓我們執(zhí)行構(gòu)建操作。如圖:

在點(diǎn)擊之前需要在Assets目錄下創(chuàng)建AssetBundles文件夾。點(diǎn)擊之后將彈出一個進(jìn)度條對話框,完成后就生成了對應(yīng)的AssetBundles:

可以看到這些AssetBundles是按照我們此前在編輯器中新建的AssetBundle的目錄結(jié)構(gòu)生成的。并且有這相關(guān)的以.manifest為后綴的文件。一個manifest文件是描述了對應(yīng)資源文件的循環(huán)冗余碼(CRC)和資源依賴(asset dependencies)的文本文件。
另外,你還會看到在MyAssetBundles文件夾下有一個MyAssetBundles文件和對應(yīng)的manifest文件。每當(dāng)構(gòu)建AssetBundles時,就會創(chuàng)建這兩個文件。
4.1.3其他工具
添加下面這個腳本Editor中,可以使你獲取所有AssetBundles的名字:
GetAssetBundleNames.cs:
using UnityEditor;
using UnityEngine;
public class GetAssetBundleNames
{
[MenuItem("Assets/Get AssetBundle names")]
static void GetNames()
{
var names = AssetDatabase.GetAllAssetBundleNames();
foreach (var name in names)
Debug.Log("AssetBundle: " + name);
}
}
添加下面這個腳本Editor中,可以使你在改變AssetBundle時得到通知:
MyPostprocessor.cs:
using UnityEngine;
using UnityEditor;
public class MyPostprocessor : AssetPostprocessor
{
void OnPostprocessAssetbundleNameChanged(string path,
string previous, string next)
{
Debug.Log("AB: " + path + " old: " + previous + " new: " + next);
}
}
4.1.4AssetBundle Variants
AssetBundle Variants是Unity5的新特性。你可以將兩組不同的資源指定為同一個AssetBundle但是指定不同的Variants,這樣,你可以根據(jù)平臺的不同加載不同的資源(例如支持高清資源的設(shè)備加載hd的Variants,不支持高清資源的設(shè)備加載sd的Variants)??墒鞘褂?a target="_blank" rel="nofollow">AssetImporter.assetBundleVariant設(shè)置Variants。
4.1.5編碼建議
1.標(biāo)記AssetBundle
使用AssetImporter.assetBundleName來設(shè)置AssetBundle的名字。
2.使用函數(shù)BuildPipeline.BuildAssetBundles()構(gòu)建AssetBundle
函數(shù)原型:
public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions = BuildAssetBundleOptions.None, BuildTarget targetPlatform = BuildTarget.WebPlayer);
3.操縱Asset database中的AssetBundle names接口:
AssetDatabase.GetAllAssetBundleNames()
AssetDatabase.GetAssetPathsFromAssetBundle
AssetDatabase.RemoveAssetBundleName()
AssetDatabase.GetUnusedAssetBundleNames()
AssetDatabase.RemoveUnusedAssetBundleNames()
AssetPostProcessor.OnPostprocessAssetbundleNameChanged
4.構(gòu)建AssetBundle選項(xiàng)(BuildAssetBundleOptions)
CollectDependencies 和 DeterministicAssetBundle 選項(xiàng)總是啟用的。
CompleteAssets 如果我們總是從assets開始而不是objects,該項(xiàng)將被忽略。它默認(rèn)是完整的。
ForceRebuildAssetBundle 即便你沒有改變資源,但是通過設(shè)置該項(xiàng)你可以強(qiáng)制從新構(gòu)建資源。
IngoreTypeTreeChanges 即便你改變了type tree你也可以通過設(shè)置該項(xiàng)忽略掉。
DisableWriteTypeTree 與 IngoreTypeTreeChanges是沖突的,如果你將type tree設(shè)置為不啟用則無法忽略。
5.Manifest file
每個AssetBundle都有一個manifest文件,包含如下信息:
CRC(循環(huán)冗余碼)
資源文件的哈希碼。在該AssetBundle中的所有資源有一個單一的哈希碼,用于檢查增量的構(gòu)建。
Type tree哈希碼。在該AssetBundle中所有類型有一個單一的哈希碼,用于檢查增量的構(gòu)建。
Class types。該AssetBundle中所有的類類型。當(dāng)為type tree做增量構(gòu)建檢查時將產(chǎn)生一個新的哈希碼。
Asset names。該AssetBundle中所有明確包含的資源名字。依賴的AssetBundle的名字。依賴于該AssetBundle的其他AssetBundles。
manifest文件僅用于檢查增量構(gòu)建,運(yùn)行時不需要。因此不需要打包進(jìn)正式發(fā)行的游戲中。
6.Single manifest file
一個單一的manifest文件一般包含以下信息:
所有的AssetBundles。
所有AssetBundles的依賴信息。
7.Single manifest AssetBundle
一個AssetBundleManifest對象有如下APIs:
GetAllAssetBundles() 返回本次構(gòu)建的所有AssetBundles名字。
GetDirectDependencies() 返回直接依賴的AssetBundle名字。
GetAllDependencies() 返回所有依賴的AssetBundle名字。
GetAssetBundleHash(string) 返回指定的AssetBundle的哈希碼。
GetAllAssetBundlesWithVariant() 返回所有AssetBundles帶Variant的名字。
8.AssetBundle 加載APIs
Unity5.x改為如下APIs:
AssetBundle.GetAllAssetNames() 返回該AssetBundle中的所有資源名。
AssetBundle.GetAllScenePaths() 如果該AssetBundle是一個場景文件,返回該場景中所有資源的路徑。
AssetBundle.LoadAsset() 從該AssetBundle中加載資源。
AssetBundle.LoadAllAssets() 從該AssetBundle中加載所有資源。
AssetBundle.LoadAssetWithSubAssets() 通過名字加載該AssetBundle中的資源及子資源。
還有對應(yīng)的異步接口也有提供。
組件類型不在返回了,你可以在加載了GameObject之后從其獲取。
9.Typetrees
每個AssetBundle中都默認(rèn)寫入了一個typetree。只有Metro(Windows Store Apps)例外,它有不同的序列化方案。
參考鏈接:
http://docs.unity3d.com/Manual/AssetBundlesIntro.html
http://docs.unity3d.com/Manual/BuildingAssetBundles.html
http://docs.unity3d.com/ScriptReference/BuildPipeline.BuildAssetBundles.html