(1)新版本 唯一打包API Buildpipeline.BuildAssetBundle
(2)在資源的Inpector界面最下方可設置該資源的assetbundleName,
每個assetbundleName對應一個Bundle,即assetbundleName相同的資源會打在一個Bundle中。
(3),我們還可以在Inpector中設置另一個名字,即variant(變體)。在打包時,variant會作為后綴添加在assetbundleName之后。(差異區分,例如相同名字的Normal和HD的區別)
AssetBundleName,名字固定為小寫,每個AssetBundle都可以設置一個Variant,其實就是一個后綴,實際上AssetBundle會添加這個后綴。如果有不同分辨率的同名資源,可以使用這個來區分。
值得注意的是:
AssetBundleName是可以帶’/’符號的,這是一個很好的設計,因為我們打包的資源會很多,如果打包生成的所有AssetBundle都生成在同一個文件目錄里,這肯定是很難管理的。不過名稱引入’/’便可以很好解決這個問題。我們通過名字中設置類似”npc/demon/jushiguai.unity3d”這樣的名字。那么在生成AssetBundle的時候會自動根據名字生成文件目錄。這樣生成的AssetBundle有了分類就很好管理了。如下圖:
關於Assetbundle 中的腳本,在移動平台下Assetbundle里面放的腳本是不會被執行的,我們打包前給兩個Prefab掛上了腳本嗎?在手機上將Assetbundle下載到本地后,加載進游戲中Prefab會自動在本地找它身上掛着的腳本,他是根據腳本的名來尋找,如果本地有這條腳本的話,Prefab會把這個腳本重新綁定在自身,並且會把打包前的參數傳遞進來。如果本地沒有,身上掛的條腳本永遠都不會被執行。
優化建議:
提供腳本批量對資源設置assetbundleName。
規划好assetBundle所對應的資源類型,規划好assetBundle的數量。
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);
加載:
運行時加載AssetBundle對象主要可以分為兩大類途徑:
先獲取WWW對象,再通過WWW.assetBundle獲取AssetBundle對象
直接獲取AssetBundle
下面我們就具體分析一下這兩種途徑:
先獲取WWW對象,再通過WWW.assetBundle加載AssetBundle對象:
在先獲取WWW對象,在獲取AssetBundle的這種方式中,我們可以使用以下兩個API來實現這個功能。
public WWW(string url),直接調用WWW類的構造函數,目標AssetBundle所在的路徑作為其參數,構造WWW對象的過程中會加載Bundle文件並返回一個WWW對象,完成后會在內存中創建較大的WebStream(解壓后的內容,通常為原Bundle文件的4~5倍大小,紋理資源比例可能更大),因此后續的AssetBundle.LoadAsset可以直接在內存中進行。(無論是服務器路徑還是本地路徑下載操作都一樣)但是bundle只能保存在內存中,也就是退出游戲在進入還得重新下載:),顯然我們實際開發中不會這樣用。
public static WWW LoadFromCacheOrDownload(string url, int version, uint crc = 0),WWW類的一個靜態方法,調用該方法同樣會加載Bundle文件同時返回一個WWW對象,和上一個直接調用WWW的構造函數的區別在於該方法會將解壓形式的Bundle內容存入磁盤中作為緩存(如果該Bundle已在緩存中,則省去這一步),完成后只會在內存中創建較小的SerializedFile,而后續的AssetBundle.LoadAsset需要通過IO從磁盤中的緩存獲取。
直接加載AssetBundle對象:
在4.x時代,我們可以通過CreateFromFile或CreateFromMemory方法將磁盤上的文件或內存中的流構造成我們需要的AssetBundle對象。但是在5.x版本中,曾經的這兩個方法已經被新的LoadFromFile、LoadFromMemory方法所代替(這兩個方法還有異步的版本),且機制上也有了一些區別。
public static AssetBundle LoadFromFile(string path, uint crc = 0):新的從文件創建加載AssetBundle方法和4.x中的CreateFromFile方法在機制上有了一些分別,舊的CreateFromFile必須使用未壓縮的Bundle文件才能在運行時動態創建AssetBundle對象。而新的LoadFromFile方法則沒有這個要求,它支持上一節中提到的幾個壓縮格式,針對LZ壓縮格式和未壓縮的磁盤上的bundle文件,該方法會直接加載。針對使用默認的LZMA壓縮格式壓縮的bundle文件,該方法會在幕后先將bundle文件解壓后再加載。這是最快的加載AssetBundle的方式。該方法是同步版本,還有異步版本:LoadFromFileAsync。
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0):從內存中獲取Bundle的二進制數據,同步地創建AssetBundle對象。該方法一般用在經過加密的數據上,經過加密的流數據經過解密之后我們可以調用該方法動態的創建AssetBundle對象。該方法是同步版本,還有異步版本:LoadFromMemoryAsync。
實際使用環境的分析:
(1) 隨游戲一同發布的AssetBundle(一般位於StreamingAssets文件夾中):
在打AssetBundle包時,使用LZ4壓縮格式進行打包(開啟BuildAssetBundleOptions.ChunkBasedCompression即可)。
在運行時需要加載AssetBundle對象時,使用LoadFromFile方法進行加載。
這樣做的好處是:即可以將AssetBundle文件壓縮,又可以兼顧加載速度,且節約內存。
(2) 作為更新包,需要從服務端下載的AssetBundle:
在打AssetBundle包時,使用默認的LZMA格式壓縮。
使用WWW.LoadFromCacheOrDownload方法下載並緩存AssetBundle包文件。
這樣做的好處是:獲得了最大的壓縮率,在下載過程中可以減少數據傳輸量。同時,在本地磁盤創建緩存之后,又可以兼顧之后的加載速度,且節約內存。
(3) 進行加密的AssetBundle:
在打AssetBundle包時,使用LZ4壓縮格式進行打包(開啟BuildAssetBundleOptions.ChunkBasedCompression即可)。
在運行時需要加載AssetBundle對象時,使用LoadFromMemory方法進行加載。(這也是從內存中使用流數據加載AssetBundle對象的僅有的使用場景。)
(4)需要自己壓縮的AssetBundle:
我們自己也可以使用第三方庫或工具對生成的AssetBundle包文件進行壓縮,如果需要這樣做,則我們最好不要再使用Unity3D對AssetBundle進行壓縮,因此在打包時選擇開啟BuildAssetBundleOptions.UncompressedAssetBundle。
在運行時需要加載AssetBundle對象時,使用LoadFromFileAsync方法進行異步加載。
資源加載:
新版的AssetBundle中,加載資源的API已經變成了以下的幾個:
LoadAsset:從資源包中加載指定的資源
LoadAllAsset:加載當前資源包中所有的資源
LoadAssetAsync:從資源包中異步加載資源
卸載資源:
資源卸載部分的變化不大,使用的仍然是Unload方法。
Unload()
該方法會卸載運行時內存中包含在bundle中的所有資源。
當傳入的參數為true,則不僅僅內存中的AssetBundle對象包含的資源會被銷毀。根據這些資源實例化而來的游戲內的對象也會銷毀。
當傳入的參數為false,則僅僅銷毀內存中的AssetBundle對象包含的資源。
其他:
新增打包模式
ForceRebuildAssetBundle : 強制重新打包所有AssetBundle文件,一般情況只做增量打包。
IgnoreTypeTreeChanges : 用於判斷AssetBundle更新時,是否忽略TypeTree的變化。
AppendHashToAssetBundleName : 將Hash值添加在AB包文件名之后,開啟后可通過文件名來判斷哪些AB進行了更新。
依賴項相關:
雖然Unity說會幫我們處理好依賴關系,但是只是說能夠方便獲取一個asset的依賴項,並不會幫你自動加載所有依賴項。所以我們加載的代碼還是三個部分:加載依賴項和加載自身,卸載依賴項。
Dependencies(資源依賴關系):當某個資源依賴其它AB 包中的文件時候,manifes(清單)文件中顯示依賴關系。