天天看點

【Unity優化】資源管理系列03:AssetBundle 基本原理

定義:将一個或多個檔案,按照一種歸檔格式,存在一個檔案中,Unity可以索引并序列化其中的檔案

操作:加載/解除安裝AB自身、加載解除安裝AB中某個資源

作用:在遊戲安裝後,繼續分發和更新非代碼資源

1)減小遊戲包體

2)減小運作時記憶體壓力

3)針對不同裝置/平台,加載不同資源

AB結構

1)資料頭:identifier、壓縮類型、manifest

manifest:查找表,key是對象名,value中包含一個位元組索引,定位資料段中對象位置

2)資料段:資源系列化後的原始資料

三種壓縮類型

1)LZMA:所有資源的序列化資料,被壓縮進同一個位元組數組

2)LZ4:每個資源的序列化資料,單獨被壓縮為位元組資料

3)不壓縮:原始位元組資料

壓縮類型對比

1)LZMA:

優點:原始AB小

缺點:想要加載其中一個資源,需要解壓整個AB;運作時占用記憶體大

2)LZ4(推薦):

優點:想要加載其中一個資源,隻需要解壓相關資料塊;運作時占用記憶體小

缺點:原始AB大

加載AB

1)AssetBundle.LoadFromMemory

說明:不推薦,兩倍AB記憶體占用,三倍資源記憶體占用

2)AssetBundle.LoadFromFile

說明:推薦,隻加載資料頭,之後按需加載資源

補充:在Editor模式下,異步方法會加載整個AB,會出現記憶體峰值;真機中沒有

3)UnityWebRequest 的 DownloadHandlerAssetBundle

① 可以使用 UnityWebRequest.GetAssetBundle,也可使用 DownloadHandler

② DownloadHandler 使用工作線程,流式下載下傳,存入固定大小buffer,然後傳給臨時存儲或 AB cache。這些操作都有原生代碼實作,不會産生堆配置設定。且不會額外儲存下載下傳位元組資料的拷貝,減少記憶體占用。

③ 如果AB是LZMA壓縮格式,在下載下傳的時候會被解壓縮,并以LZ4格式緩存。

④ AB下載下傳完成後,通過 DownloadHandler 的 assetBundle 擷取AB。

⑤ 如果AB之前已被加載,且在緩存中,則會立即傳回,此時和 LoadFromFile 功能類似

4)WWW.LoadFromCacheOrDownload

說明:Unity5.6之前使用,已廢棄

5)建議

① LoadFromFile,建議在任何可用的場景使用,無論是加載速度、硬碟占用、運作時記憶體占用,該API都是最高效的。

② UnityWebRequest,需要下載下傳AB時使用;記得調用 Dispose 或 Using。

③ 如果自研下載下傳器,需要适配 LoadFromFile 方法。

加載AB中資源

1)三種API

① LoadAsset(Async)

② LoadAllAssets(Async)

③ LoadAssetWithSubAssets(Async)

2)同步與異步對比

① 同步方法:至少比異步快一幀;缺點是在資源加載完畢前,會阻塞主線程

② 異步方法:可以在一幀内加載多個資源,不阻塞主線程

3)LoadAllAssets(Async)

适用場景:從一個AB中加載大部分資源,且這些資源互相獨立。

優點:比多次調用 LoadAsset 快

AB政策:如果一個AB中,超過66%的資源需要同時加載,則建議将這部分分離出來單獨打包

4)LoadAssetWithSubAssets(Async)

适用場景:當需要加載一個由多個小資源組合而成的大資源時

舉例:FBX模型及其動畫、精靈圖集及其精靈

5)資源加載的一些細節

① 從存儲中加載對象資料,發生在工作線程上。

② 多個工作線程,使得多個對象可以同時被反序列化、處理、整合。

③ 當一個對象被加載完畢,Awake方法被調用,從下一幀開始,該對象可被引擎使用。

④ 對象加載在一幀中的時間不超過 time-slice,該值由 ThreadPriority 決定。

⑤ 發起異步調用,和對象被引擎可用,這兩步間至少需要一幀,是以相同條件下,同步方法要比異步方法快一幀。

6)AB依賴

① AB間的互相依賴可以通過 AssetDatabase 和 AssetBundleManifest 擷取

② 在加載一個對象前,要先加載它依賴的所有AB。Unity不會幫忙自動加載,要自己實作

7)AssetBundle manifests

① 被包含在一個以父檔案夾命名的AB中

② 包含了AB中對象之間的引用資訊

③ manifest AB 和其他 AB 一樣,可以被加載、緩存、解除安裝

④ 使用 GetAllAssetBundles 方法擷取所有包含 AB 清單

⑤ 使用 GetAllDependencies 方法傳回該AB的所有依賴

⑥ 使用 GetDirectDependencies 方法傳回該AB的直接依賴

⑦ 上面兩個方法都會配置設定 string 數組,不要在性能敏感處使用

8)建議

① 在性能敏感的代碼之前,盡可能預加載需要的資源

繼續閱讀