Unity AssetBundles and Resources指引 (三) AssetBundle基础
本文內容主要翻譯自下面這篇文章
https://unity3d.com/cn/learn/tutorials/topics/best-practices/guide-assetbundles-and-resources?playlist=30089? A guide to AssetBundles and Resources
?
第三部分 AssetBundle基礎
3.1概覽
AssetBundles系統提供一種手段把一個或多個Asset文件歸檔并能夠被unity索引。目的就是分發能這些能夠兼容unity序列化系統的數據,是安裝后用來更新非代碼內容的主要工具。使得能夠減少安裝包的尺寸和運行時內存壓力。以及根據終端設備可選加載優化內容稱為可行。
理解AssetBundle工作流程是構建成功的Unity移動設備項目的關鍵。
?
? 3.2 什么是AssetBundle
一個AssetBundle包含兩個部分:頭部和數據部分。
頭部是在構建AssetBundle時unity生成的。存放AssetBundle的信息,比如AssetBundle標記,AssetBundle是否壓縮和一分清單。清單是有Object的名字作為索引的查找表。每個查找項提供一個給定名字的Object在數據段位置的字節索引。數據段包含所有Assets的序列化后的原始數據。如果數據段是壓縮的。LZMA是整個數據段進行壓縮的。即先把所有的Assets序列化,然后把整個字節流進行壓縮。
unity5.3之前,AssetBundle內部不能單個Object壓縮。如果是使用5.3之前的版本,如果要讀取一個或者多個Obect,Unity就要解壓整個AssetBundle。一般來說unity會緩存未壓縮的版本來提高以后的加載效率。
5.3加入了LZ4壓縮選型。用LZ4選項構造的AssetBundle會以單個Object為單位進行壓縮。是的加載單個Object不用解壓整個AssetBundle。
3.3 AssetBundle管理器
?? Unity開發了一個AssetBundle的開源參考實現,可以從https://bitbucket.org/Unity-Technologies/assetbundledemo下載。
3.4 加載AssetBundle
在Unity5里面,AssetBundle可以通過4個API加載AssetBundle。這四個api會隨著以下兩個情況行為有所不同
這四個Api分別是 AssetBundle.LoadFromMemoryAsync、 LoadFromFile、
LoadFromCacheOrDownLoad 和UnityWebRequest的DownloadHandlerAssetBundle。
3.4.1 LoadFromMemoryAsync
Unity建議不要用這個API。在5.3.2之前這個API名字叫CreateFromMemory。名字不一樣但是功能一樣。
這個方法從托管字節數組里面加載AssetBundle。他總是先將托管字節數組拷貝成本體字節數組。如果是LZMA壓縮的,拷貝的時候就進行了解壓。如果沒壓縮在原樣拷貝。
這個api至少需要兩倍的AssetBundle的尺寸內存。從AssetBundle里面加載的Asset會在內存里面拷貝3次:一次托管字節數組,一次本地內存拷貝還有一次就是Asset自身子啊GPU或者系統內存占用。
3.4.2 LoadFromFile
5.2之前叫CreateFromFile,名字不一樣,但是功能是一樣的。
如果是加載一個未壓縮的AssetBundle,這api十分高效。如果是未壓縮或者LZ4壓縮,api行為如下:
移動設備上API只加載頭信息。只要在Load一個Object才會去加載特定的對象。不會浪費別的內存。
在編輯器里面會加載整個AssetBundle進內存。
注意在安卓設備上,如果版本是5.3或者更老的版本,從StreamAssts目錄加載會失敗。因為這些內容在一個壓縮的jar包里面。5.4后面修復了這個bug。
3.4.3 LoadFromCacheOrDownLoad
如果是從遠程服務器上加載資源這是一個有用的api。如果是從本地文件系統加載可以用file://URL形式。如果內容已經存在本地緩存。這個api就和LoadFromFile一樣。
如果沒有緩存,就會從源處讀取內容,如果是壓縮的,他會用一個工作線程解壓然后寫進緩存。一旦緩存,則是未壓縮的AssetBundle。
3.4.4 AssetBundleDownLoadHandler
5.3后為移動平臺引進的api。比WWW更具彈性。允許開發者指定如果處理下載的數據以便消除不必要的內存消耗。
3..4.5 建議
一般來說,盡量使用LoadFromFile API。他更有效速度更快。如果需要從遠程下載資源,5.3或更新的版本建議用UnityWebRequest,老的版本用WWW。
3.5 從AssetBundle加載Asset
可以用三個不同的api從AssetBundle加載Object:LoadAsset、LoadAllAsset和LoadAssetWithSubAsset。這些api都有異步版本。同步api會比異步要快至少1幀。在5.1或者更老的版本可以這么說。因為在這些版本中一幀至多只加載一個Object。這意味著加載多個Object的異步api版本會比相應的同步版本慢很多。5.2之后修復了這個問題??梢栽僖粠锩婕虞d多個Object,加載多少要視設置的時間片。
當要加載多個不相關的Object時應該用LoadAllAssets。但是也只有在加載大部分或者全部時才使用。相比另外兩個API,LoadALL版本會稍微快一些。但是如果AssetBundle里面資源很多,而要加載的不超過三分之二。建議重新分割AssetBundle為多個更小的AssetBundle,然后調用LoadAll版本。
加載細節:
加載不是在主線程上面運行的。其中數據讀取是在工作線程上執行的。5.3之前加載對象是順序執行,而且某些部分職能在主線程上面執行。當工作線程讀完數據。他就會暫停執行讓主線程進行整合集成(integration),直到主線程整合完畢才繼續工作。5.3之后,對象加載可以并行。多個對象可以再工作線程上面反序列化,處理和整合。當對象完成加載。Awake回調會執行,然后在下一幀就可用了。
3.5.2 AssetBundle依賴
Unity5 的AssetBundle系統。AssetBundle的依賴關系是可以通過兩個不同的api自動跟蹤的。在編輯器里面,依賴關系可以通過assetdatabase api來查詢。AssetBundle的分配和依賴可以通過AssetImporter API來訪問和改變。運行時可以通過ScriptableObject的子類的 AssetBundleManifest API來訪問。
如果一個AssetBundle的object引用到一個或者多個另外一個AssetBundle的Object,我們就稱為AssetBundle依賴。就像第一部分描述的,AssetBundle可以作為其內部包含的object的本地ID和GUID的數據源。
因為Object只有在實例ID首次被引用時才加載。而且AssetBundle被加載的時候,才會被賦予一個正確的實例ID。因此AssetBundle加載的順序是無關的。重要的是要先于加載一個對象之前先加載它所依賴的AssetBundle們。Unity不會自動加載所有的依賴AssetBundle,這是開發者的責任。
比如一個材質A引用一個貼圖B。A打包進AssetBundle1,B打包進AssetBundle2.在這個用例中,AssetBundle2必須先與從AssetBundle1中加載材質A之前加載。但這并不要AssetBundle2比AssetBundle1先加載。
Unity不會再AssetBundle1加載的時候自動加載AssetBundle2.這必須手工通過腳本加載。而且加載AssetBundle1和2的api是無關的。無論是通過哪種api加載都可以。
3.5.3 AssetBundle清單
當通過buildpipeline生成AssetBundle時候,unity會生成一個依賴關系信息到一個單獨的AssetBundle里面。放在所有的AssetBundles存放的共同父目錄里面。他的里面存放了一個 AssetBundleManifest類型。它提供了一個GetAllAseetBundles API來查詢所有的AssetBundle。 GetAllDependencies返回所有的依賴。包括一個依賴的依賴,以及依賴的依賴的依賴等等。GetDirectDependencies只返回直接依賴。、
3.5.4 建議
建議只加載所需要的對象。特別是移動平臺上,因為他們本地存儲讀取速度非常慢,而且加載和卸載Object會觸發垃圾回收。
轉載于:https://www.cnblogs.com/qzzlw/p/5950487.html
總結
以上是生活随笔為你收集整理的Unity AssetBundles and Resources指引 (三) AssetBundle基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老是梦到和亲人吵架是怎么回事
- 下一篇: CentOS 7 yum 安装php5.