本文的主要內容是分析5.X版本的AssetBundle機制(包括建立資源包、壓縮資源包、加載資源包和從資源包中加載/卸載資源等幾個方面)及其關鍵的API使用方式。
AssetBundle是Unity推薦的資源管理方式,官方列舉了諸如熱更新,壓縮,靈活等等優勢。算法
使用步驟
1、打包
1.經過Editor中的UI爲AssetBundle標記資源。並且一個資源和對應的AssetBundle的映射將會在資源數據庫(AssetDatabase)中被建立。數據庫
2.BuildPipeline.BuildAssetBundles():咱們只須要提供一個輸出AssetBundle的地址便可。引擎將自動根據資源的assetbundleName屬性(即在上文中UI中設置的值)批量打包,自動創建Bundle以及資源之間的依賴關係。
Unity3D爲咱們提供了惟一的API用來打AssetBundle包。即:BuildPipeline.BuildAssetBundles
在腳本中調用BuildPipeline.BuildAssetBundles,U3D將自動根據資源的assetbundleName屬性批量打包,自動創建Bundle和資源之間的依賴關係。在資源的Inpector界面最下方可設置該資源的assetbundleName,每一個assetbundleName對應一個Bundle,即assetbundleName相同的資源會打在一個Bundle中。若是所依賴的資源設置了不一樣的assetbundleName,則會自動與之創建依賴關係,避免出現冗餘,從而減少Bundle包的大小。固然,除了能夠指定assetbundleName,咱們還能夠在Inpector中設置另外一個名字,即variant。在打包時,variant會做爲後綴添加在assetbundleName以後。相同assetbundleName,不一樣variant的Bundle是能夠相互替換的。緩存
設置好以後,咱們只須要建立一個新的腳本,經過編輯器拓展調用BuildPipeline.BuildAssetBundles方法便可:異步
BuildPipeline.BuildAssetBundles方法的參數
outputPath:輸出目錄,通常咱們設置爲 Application.streamingAssetsPath + Bundle的目標路徑和Bundle名稱
targetPlatform:目標平臺,在安卓,IOS,PC下,咱們須要傳入不一樣的平臺標識,以打出不一樣平臺適用的包,注意,Windows平臺下打出來的包,不能用於IOS
BuildAssetBundleOptions:BuildAssetBundleOptions.CollectDependencies會去查找依賴,BuildAssetBundleOptions.CompleteAssets會強制包含整個資源,BuildAssetBundleOptions.DeterministicAssetBundle會確保生成惟一ID,在打包依賴時會有用到編輯器
Unity3D引擎爲咱們提供了三種壓縮策略來處理AssetBundle的壓縮,即:LZMA格式、LZ4格式、不壓縮。
LZMA格式:在默認狀況下,打包生成的AssetBundle都會被壓縮。在U3D中,AssetBundle的標準壓縮格式即是LZMA(LZMA是一種序列化流文件),所以在默認狀況下,打出的AssetBundle包處於LZMA格式的壓縮狀態,在使用AssetBundle前須要先解壓縮。
使用LZMA格式壓縮的AssetBundle的包體積最小(高壓縮比),可是相應的會增長解壓縮時的時間。
LZ4格式: Unity 5.3以後的版本增長了LZ4格式壓縮,因爲LZ4的壓縮比通常,所以通過壓縮後的AssetBundle包體的體積較大(該算法基於chunk)。可是,使用LZ4格式的好處在於解壓縮的時間相對要短。若要使用LZ4格式壓縮,只須要在打包的時候開啓BuildAssetBundleOptions.ChunkBasedCompression便可。
BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
BuildAssetBundleOptions.ChunkBasedCompression);
不壓縮:咱們也能夠不對AssetBundle進行壓縮。沒有通過壓縮的包體積最大,可是訪問速度最快。若要使用不壓縮的策略,只須要在打包的時候開啓BuildAssetBundleOptions.UncompressedAssetBundle便可。
BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
BuildAssetBundleOptions.UncompressedAssetBundle);函數
在打包的時候,咱們須要對包的大小和數量進行一個平衡,全部資源打成一個包,一個資源打一個包,都是比較極端的作法,他們的問題也很明顯,更多狀況下咱們須要靈活地將他們組合起來
打成一個包的缺點是加載了這個包,咱們不須要的東西也會被加載進來,佔用額外內存,並且不利於熱更新 打成多個包的缺點是,容易形成冗餘,首先影響包的讀取速度,而後包之間的內容可能會有重複,且太多的包不利於資源管理哪些模塊打成一個包,哪些模塊打成多個包,須要根據實際狀況來,例如遊戲中每一個怪物都須要打成一個包,由於每一個怪物之間是獨立的,例如遊戲的基礎UI,能夠打成一個包,由於他們在各個界面都會出現
PS.想打包進AssetBundle中的二進制文件,文件名的後綴必須爲「.bytes」ui
2、加載
首先獲取AssetBundle對象,第二從AssetBundle中加載目標資源。在運行時加載AssetBundle對象主要能夠分爲兩大類途徑:
1.先獲取WWW對象,再經過WWW.assetBundle加載AssetBundle對象:
public WWW(string url),直接調用WWW類的構造函數,目標AssetBundle所在的路徑做爲其參數,構造WWW對象的過程當中會加載Bundle文件並返回一個WWW對象,完成後會在內存中建立較大的WebStream(解壓後的內容,一般爲原Bundle文件的4~5倍大小,紋理資源比例可能更大),所以後續的AssetBundle.LoadAsset能夠直接在內存中進行。
public static WWW LoadFromCacheOrDownload(string url, int version, uint crc = 0),WWW類的一個靜態方法,調用該方法一樣會加載Bundle文件同時返回一個WWW對象,和上一個直接調用WWW的構造函數的區別在於該方法會將解壓形式的Bundle內容存入磁盤中做爲緩存(若是該Bundle已在緩存中,則省去這一步),完成後只會在內存中建立較小的SerializedFile,然後續的AssetBundle.LoadAsset須要經過IO從磁盤中的緩存獲取。LoadFromCacheOrDownload會記錄全部Bundle的使用狀況,並在適當的時候刪除最近不多使用的資源包,它容許存在兩個版本號不一樣但名字同樣的資源包,這意味着你更新這個資源包以後,若是沒有更新代碼中的版本號,你可能取到的會是舊版本的資源包,從而產生其餘的一些BUG。另外,當你的磁盤空間不足的時候(硬盤爆了),LoadFromCacheOrDownload只是一個普通的new WWW
2.直接加載AssetBundle對象:
public static AssetBundle LoadFromFile(string path, uint crc = 0):新的從文件建立加載AssetBundle方法,loadFromFile方法支持上一節中提到的幾個壓縮格式,針對LZ壓縮格式和未壓縮的磁盤上的bundle文件,該方法會直接加載。針對使用默認的LZMA壓縮格式壓縮的bundle文件,該方法會在幕後先將bundle文件解壓後再加載。這是最快的加載AssetBundle的方式。該方法是同步版本,還有異步版本:LoadFromFileAsync。
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0):從內存中獲取Bundle的二進制數據,同步地建立AssetBundle對象。該方法通常用在通過加密的數據上,通過加密的流數據通過解密以後咱們能夠調用該方法動態的建立AssetBundle對象。該方法是同步版本,還有異步版本:LoadFromMemoryAsync。
3、資源加載
LoadAsset:從資源包中加載指定的資源
LoadAllAsset:加載當前資源包中全部的資源.
LoadAssetAsync:從資源包中異步加載資源
在Bundle中加載的Prefab是不能直接使用的,它須要被實例化以後,才能使用,而對於這種Prefab,實例化以後,這個Bundle就能夠被釋放了
GameObject obj = GameObject.Instantiate(bundle.Load("MyPrefab")) as GameObject;
bundle.Load("MyPrefab", typeof(GameObject))加載的時候最好傳入資源的類型加密
4、針對項目的建議
因爲以上分析的幾種加載手段各有各的使用情景和特色。所以建議在咱們的項目中按照如下情景使用這些方法:
1.隨遊戲一同發佈的AssetBundle(通常位於StreamingAssets文件夾中):在打AssetBundle包時,使用LZ4壓縮格式進行打包(開啓BuildAssetBundleOptions.ChunkBasedCompression便可)。
2.在運行時須要加載AssetBundle對象時,使用LoadFromFile方法進行加載。
這樣作的好處是:便可以將AssetBundle文件壓縮,又能夠兼顧加載速度,且節約內存。
3.在打AssetBundle包時,使用默認的LZMA格式壓縮。
4.使用WWW.LoadFromCacheOrDownload方法下載並緩存AssetBundle包文件。url