前言
看了一些資料:
對Unity5.x后的AssetBundle依賴機制有了一點理解,創建了一個項目驗證 github:GeWenL/AssetBundlePro AbScene.unity
目錄
- 設置導出ab的名字
- 打包命令與壓縮格式
- 依賴(Dependencies)-避免資源冗余,使用UnityStudio驗證。
- 基于依賴打包資源總結
一、設置導出ab的名字
- 編輯器設置
- 腳本設置,繼承AssetPostprocessor(編輯器類,一個資源導入的管理器),OnPostprocessAllAssets是所有的資源的導入,刪除,移動,都會調用此方法:
// 設置導出ab的名字
public class AssetBundleImporter : AssetPostprocessor
{
// 全部資源加載完畢之后調用
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets,
string[] movedFromAssetPaths)
{
foreach (var item in importedAssets)
{
...
var importer = AssetImporter.GetAtPath(item);
importer.assetBundleName = abName;
...
}
}
}
資源有哪些? Some common types of Asset
二、打包命令與壓縮格式
assetbundle打包命令是BuildPipeline.BuildAssetBundles
,格式有:
- LZMA 默認 (None)
- 不壓縮 (UncompressedAssetBundle)
- LZ4 (ChunkBasedCompression):Unity5.3之后支持
LZ4是塊壓縮(chunk-based),LZMA是流壓縮(stream-based)。流壓縮(LZMA)在處理整個數據塊時使用同一個字典,它提供了最大可能的壓縮率但只支持順序讀取。塊壓縮(LZ4)指的是原始數據被分成大小相同的子塊并單獨壓縮。如果你想要實時解壓/隨機讀取開銷小,則應該使用這種。
LZMA壓縮方式的優點在于使用同一個字典壓縮率較高,但只能順序讀取意味著加載任意一個資源時,都需要將整個AssetBundle解壓,造成卡頓和額外內存占用。LZ4基于塊壓縮率較低(測試LZMA換LZ4:86.9M -> 108M),但只需解壓需要的塊即可,不會有大的卡頓和額外內存占用。
三、依賴(Dependencies)-避免資源冗余
依賴的處理不當是導致資源冗余的重要原因。
我的測試項目采用不壓縮(UncompressedAssetBundle)的方式;
4個Sprite紋理(不壓縮),tex1-4; 單獨打成不壓縮的ab包,大小如下圖所示。
現在有5個prefab,sprite1.prefab
關聯紋理tex1, sprite2.prefab
關聯紋理tex2, sprite3.prefab
關聯紋理tex3, sprite12.prefab
關聯紋理tex1/tex2, sprite123.prefab
關聯紋理tex1/tex2/tex3.
將這5個prefab分別打ab包,prefabsp1、prefabsp2、prefabsp3、prefabsp12、prefabsp123.
分成兩種情況:
1. 紋理tex1-4打成ab包
這5個prefab ab包體積很小,僅僅關聯了紋理ab包
例如sprite1和sprite123兩個prefab ab包的manifest文件,展示了關聯的的tex1.png、tex2.png、tex3.png已經打在了對應的ab包中,因此要依賴對應的ab包,Dependencies是依賴ab列表。
此時,僅加載sprite123.prefab(AssetBundle.LoadFromFile + bundle.LoadAsset + Instantiate):
會發現使用tex1.png、tex2.png、tex3.png的Image對象上的圖已經missing,顯示也為錯誤的白色。原因是prefabsp123不包含圖片這3張圖片(UnityStudio驗證),只加載它,沒有辦法找到對應紋理。
想要正常顯示,需要提前加載tex1.png、tex2.png、tex3.png對應的ab包,例如提前加載tex1、tex2 ab包,效果如下:(tex1、tex2 正常顯示,但tex3未加載也未正常顯示)
AssetBundle.LoadFromFile(Application.dataPath + "/../MyBundle/tex1");
AssetBundle.LoadFromFile(Application.dataPath + "/../MyBundle/tex2");
2. 紋理tex1-4不打成ab包
使用UnityStudio查看ab包能看出,prefabsp1不僅包含sprite1.prefab,還寫入(written out to this single file
)了Sprite-tex1.png,同樣prefabsp12、prefabsp123也擁有一份自己的tex1.png,如下圖所示。
這種打包方式,被多次引用到的資源將在每個用到它的AssetBundle獨自存在一份。也就是常常提到的資源冗余。
三份tex1自然有三份內存占用,傳遞給顯卡時也需要傳遞三份,cpu也無法對使用不同圖的渲染命令進行合并優化,哪怕它們是一模一樣的tex1.png。
四、基于依賴打包資源總結
核心是:避免資源冗余
做法是:
- 對于多次引用的資源,必須明確出現在某個AssetBundle的資源列表中(Assets),Unity才能形成依賴關系,不重復打包。
- 合理劃分ab包,例如公共的資源單獨抽出來做一個AssetBundle。
- 使用工具,檢測資源是否冗余,例如UnityStudio(查看AssetBundle)、UWA檢測工具
- 注意圖集與AssetBundle的關系,一個AssetBundle可以包含多個圖集,但一個圖集的資源只能存在于一個AssetBundle中。