Unity5 AssetBundle的一些整理(一)

王王王渣渣發表於2018-03-15

最近整理一些AssetBundle的知識,包括AB的打包(差異包),讀取等。是一個比較大的功能點,在這記錄一下,以免後面自己也亂了。要是有什麼錯誤的地方歡迎各位看客指出。第一篇的話就說說AB最基礎的實現。


首先當然是什麼是AssetBundle,網上有很多的詳細介紹,我個人的理解就是,AssetBundle指把Asset資源例如,Texture圖片,Prefab預設,Animation動畫這些打包成一個個的Bundle。然後在程式碼中就可以根據路徑獲取到這些Bundle,解析出裡面的Asset用於使用。

程式碼中讀取工程中的資源,還有一種方法是Resources.Load()讀取Asset/Resources資料夾下面的資源。或者是Editor環境下的UnityEditor.AssetDatabase.LoadAssetAtPath()。至於為什麼要這麼麻煩的將資源打包成AB檔案再去動態讀取,最主要的目的就是為了可以熱更新資源。

舉個例子:當你的遊戲上線了,有一天你覺得你的登入介面的按鈕不好看,想替換下登入介面的樣式。這時你可能需要在自己的專案工程中替換好樣式然後出一個新的apk或app包,然後去走包體更新的流程。這樣明顯十分的麻煩,想想蘋果爸爸的稽核流程就望而卻步。AB就可以解決上面的這個問題,首先在遊戲上線前,先將你的登入介面打包成LoginAB資源,然後使用程式碼讀取這個AB資源裡面的UI顯示在介面上。當你需要更新介面的時候,你只要把修改後的介面打成一個新的LoginAB,放到你的伺服器上,遊戲啟動的時候在伺服器下載新的LoginAB放入手機的可讀取目錄中(例如IOS的Documents下),當要顯示登入介面的時候,先判斷手機的可讀取目錄中是否有新的LoginAB,有的話則讀取該AB,不然讀取包體內原本的LoginAB。這樣進入遊戲你的登入介面就是最新的介面了(當然啟動遊戲下載伺服器上的AB和讀取下載下來的AB這塊的邏輯需要預先寫好哈)。

大致瞭解了AB的作用後,那麼接下來要做的就是如何用程式碼實現上面的這些功能,資源的打包,讀取,下載,熱更新等等。


下面列一些需要的知識點:

(1)unity5.0之後所有的資源都多了一個新的屬性AssetBundle,裡面可以填寫assetBundleName和assetBundleVariant。如下圖所示:


assetBundleName:當你給一個Asset新增assetBundleName時,即等於告訴unity這些資源是需要打包成AB的。AB的名稱就是你這裡設定的名稱,多個不同的Asset新增同一個name的的話,這些Asset會被打進同一個AB中。需要注意的是name中字母需要全部使用小寫,檔名字尾可以自定義。並且可以使用'/'符號來進行分層。例如A.prefab的assetBundleName為b/c/a.ab,那麼打出來的AB則會在指定父目錄即StreamingAssets的b資料夾裡的c資料夾下,名為a.ab。

assetBundleVariant:資源標籤(本文中暫時沒用到),在打包時,會作為字尾新增在assetbundleName之後,通常用作LOD。一個資源只可以設定個標籤。例如有兩套貼圖資源,一套高清,一套普通,然後給他們設定同樣的assetBundleName為MyAsset,高清資源的assetBundleVariant 設定為LD,普通資源設定為SD,那麼就可以根據不同裝置通過選擇載入MyAsset.LD或MyAsset.SD來切換資源庫,這樣依賴MyAsset的Prefab就可以動態切換版本了。注意,兩套資源集的asset必須完全一一對應,對於unity來說LD和SD是同一個bundld,同一時刻只能載入其中一個。

對應的結構體:

namespace UnityEditor {
    //
    // 摘要:
    //     AssetBundle building map entry.
    public struct AssetBundleBuild {
        //
        // 摘要:
        //     AssetBundle name.
        public string assetBundleName;
        //
        // 摘要:
        //     AssetBundle variant.
        public string assetBundleVariant;
        //
        // 摘要:
        //     Asset names which belong to the given AssetBundle.
        public string[] assetNames;
        //
        // 摘要:
        //     Addressable name used to load an asset.
        public string[] addressableNames;
    }
}

(2)打包的相關指令碼:

當設定好上述屬性時,如何將它打成我們想要的AB包呢,接下來就要使用程式碼實現。在Assets/Editor目錄下新建一個指令碼,如下:

using UnityEngine;
using UnityEditor;

namespace Tool.AssetBundle {

	public class BuildAssetBundle : MonoBehaviour {

        // 打包輸出目錄,通常為StreamingAssets(若不存在該目錄需要新建一個),這是Unity的一個特殊目錄,打包時該目錄下所有資源會被打進包體中
        //StreamingAssets與Resources的區別在於,StreamingAssets不會被壓縮打進包體,而Resources會被壓縮
        public static readonly string RES_OUTPUT_PATH = "Assets/StreamingAssets";

        //MenuItem會在unity選單欄新增自定義新項
        [MenuItem("CustomEditor/Build AssetBundle")]
        private static void Build() {
            //打包,第一個引數是AB的輸出目錄,第二個引數是打包選項,第三個引數是打包的平臺,IOS,Android,Win要區分開,不然AB使用的時候會有問題。
            BuildPipeline.BuildAssetBundles(RES_OUTPUT_PATH, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
        }
    }
}
上面的這就是一段最簡單的AB打包程式碼,然後返回Unity介面,在選單欄選擇CustomEditor下面的Build AssetBundle,如圖:
就會發現在StreamingAssets下多了一個prefabs資料夾裡面有一個canvas.ab就是打包成的AB資源了。

你會發現除了canvas.ab還多了很多其他的檔案,這些留到下一篇再解釋,包括程式碼中一些需要注意的地方。

相關文章