Unity5 AssetBundle系列——基本流程


Unity5的AssetBundle修改比較大,所以第一條建議是:忘掉以前的用法,重新來!要知道,Unity5已經沒辦法加載2.x 3.x的bundle包了…
體會一下Unity5 AssetBundle的優勢:
  Cube引用Material,給Cube和Material設置不同的assetBundleName,分開打包,兩個包各自只包含自己,各自獨立。如需修改Material,只需要重打包Material即可。
  對於4.x版本,要么Cube包中會包含這個Material,導致需要重打整個Cube,要么需手動關聯Cube和Material的引用關系,在代碼中手動賦值。
  那么改進之處就是:不需要我們來管理引用關系了,不需要我們來管理引用關系了,不需要我們來管理引用關系了!可以分開打包而不需要額外的關聯代碼,對於公用資源,只需要將公用資源分開打包即可。
  測試案例:Cube1和Cube2同時引用texture,shader使用自帶的Standard

打包方式

結果

分析

Cube1、Cube2分別打包

Cube1.assetbundle 53k

Cube2.assetbundle 53k

texture重復打包

Cube1、Cube2分別打包

texture單獨打包

Cube1.assetbundle 9k

Cube2.assetbundle 9k

Texture.assetbundle 48k

texture只有一份,而且不需要代碼手動給Cube1設置使用texture,

資源撕開了,引用還在,Cool~

一、資源打包
  (1)給要打包的資源設置標記,表示對應的包名:

  

  可以使用代碼批量設置包名(只支持小寫),大致如下:

 AssetImporter ai = AssetImporter.GetAtPath(assetPath); i.assetBundleName = xxx; ai.assetBundleVariant = xxx;

  (2)生成assetbundle資源包,打包函數簡化,主要參數只需要一個輸出地址:

AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);

  調用該函數,unity會自動根據資源的標簽進行打包,而且是增量打包
  a.對於資源沒有變更的bundle包,不會觸發重新打包;
  b.資源沒變,即使生成目錄下的bundle包被刪除了,unity也不會重新打包;
  c.生成目錄下的bundle包對應的manifase被刪了,會重新打包;
  d.可以使用BuildAssetBundleOptions.ForceRebuildAssetBundle參數觸發強制重新打包。
  另外,unity提供了另一個版本的打包函數:

AssetBundleManifest BuildAssetBundles(string outputPath, AssetBundleBuild[] builds, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);

  該函數提供了不依賴資源標簽、通過代純代碼的方式打包生成資源的能力。
  (3)生成的bundle包資源目錄解析
  下圖是針對Cube.prefab生成的資源目錄結構:

  

  StreamingAssets:一個AssetBundle包,內含AssetBundleManifest類型的Asset,記錄了所有bundle包及相互間的依賴關系。
    運行時需要首先加載這個AssetBundleManifest,然后根據其提供的depence信息加載依賴的bundle包。
  StreamingAssets.manifest:全局manifest,全局manifest的名字和打包生成的目錄同名,不是固定的,這里是生成在StreamingAssets目錄下。
  Cube.assetbundle:資源bundle。
  Cube.assetbundle.manifest:每個資源自己的manifest,與bundle一一對應,只是用來做增量build,運行時根本不需要。

二、壓縮格式
  (1)LZMA:默認壓縮格式,壓縮比大,省空間,使用前需要解壓整個壓縮包;
  (2)LZ4:5.3版本新增, 40%–60% 的壓縮率,開啟BuildAssetBundleOptions.ChunkBasedCompression打包參數即可。
    LZ4算法是“基於塊”的,因此當對象從一個LZ4壓縮包加載時,僅用於該對象的相應塊會被解壓,不需要解壓整個包。
    所以LZ4和不壓縮資源一樣,都可以不解壓,而直接讀取包中的資源的。
  (3)UnCompress:不壓縮,訪問最快,費空間。
  一組測試數據:

LZMA:1.45M

LZ4:2M

UnCompress:4M

  LZ4格式壓縮比還可以,而且加載速度也很快,是大多數情況下的最優解。

三、AssetBundle加載方式對比
  主要的加載方式有以下四種,前兩種還兼具下載的功能,后兩種都有對應的異步接口:
  (1)WWW:只走內存,內存解壓、不緩存;
  (2)LoadFromCacheOrDownload:走本地cache,沒有就下載並解壓(然后再LZ4壓縮),有就用;
    如果沒有緩存,對於未壓縮的和LZ4壓縮的AssetBundle包,unity會直接把它們拷貝到緩存目錄里面,對於LZMA壓縮的,會先解壓然后重新壓縮成LZ4格式,然后緩存它。可以通過Caching.compressionEnabled控制是否壓縮緩存。
  (3)LoadFromFile:最快的方式,區別於4.x版本,可以直接使用壓縮資源;
    如果是UnCompress或LZ4,直接從disk讀取
    如果是LZMA,會先解壓到memory,然后讀取
  (4)LoadFromMemory:從內存加載,一般用於加密資源。
  使用方式建議:
  (1)隨包資源StreamingAssets:
    未壓縮或LZ4壓縮:LoadFromFile;
    LZMA壓縮:可使用 WWW.LoadFromCacheOrDownload解壓縮到本地磁盤。
  (2)熱更新資源:LZMA+WWW.LoadFromCacheOrDownload+Caching.compressionEnabled;
  (3)加密資源:LZ4+LoadFromMemory;
  (4)自己壓縮的資源:UncompressAssetBundle的AssetBundle包+自己的算法壓縮+LoadFromFileAsync。

四、資源卸載
  AssetBundle.Unload(false):干掉壓縮包,bundle不再可用,即不能再通過bundle.Load加載資源;
  AssetBundle.Unload(true):干掉壓縮包,和所有從中加載(load)出來的資源。
  所以卸載資源一般有兩種玩法:
  (1)AssetBundle.Unload(false)結合Resource.UnloadUnusedAssets()
  (2)碎片化使用AssetBundle.Unload(true)
  具體怎么用要結合游戲本身的數據特點來定制。關於要不要Unload釋放AssetBundle本身的內存,也有兩種主流玩法,一種是即用即卸(LoadAsset以后立馬釋放AssetBundle),一種是緩存AssetBundle不卸載,兩種方法各有優劣,需結合使用。

五、項目建議
  (1)對於bundle中的shader,需要避免重復打包:
  場景:Cube1使用自帶的shader Standard

打包方式

結果

分析

Cube1單獨打包,shader不進包

Cube1.assetbundle 9k

 

 

Cube1單獨打包,shader進包

Cube1.assetbundle 118k

可以看到Standard這個shader編譯后也是相當大的

  對於shader一定要注意重復打包,要么將使用的shader配置在Always Included Shaders,要么將shader也單獨打包(這種方案還沒試過) 

  

  (2)內存分析:
  一個AssetBundle壓縮包並不大,所以同時緩存100個不釋放也沒多大(4.x這個東西還是很大的,不能緩存太多)。
  AssetBundle創建,會在Not Saved/AssetBundle分組下多出一個bundle,大小4.1k:

  

  LoadAsset(cube1)后,會在Assets下多處cube1產生的asset:

  

  經測試,AssetBundle所占用的相關內存,只要管理好引用,是可以完全回收的。
  (3)資源LOD
  一個資源可以設置兩個標簽,第一個參數assetBundleName 表示包的名字,第二個參數assetBundleVariant 用來做資源的LOD。
  假設本地有兩套貼圖資源,一套高清,一套普通,然后給他們設置同樣的assetBundleName為MyAsset,高清資源的assetBundleVariant 設置為LD,普通資源設置為SD,那么就可以根據不同設備通過選擇加載MyAsset.LD或MyAsset.SD來切換資源庫,這樣依賴MyAsset的Prefab就可以動態切換版本了。
  注意,兩套資源集的asset必須完全一一對應,對於unity來說LD和SD是同一個bundld,同一時刻只能加載其中一個。
  (4)由於打包極大地簡化了,沒有指定mainAsset的過程,所以AssetBundle.mainAsset已經不能用了,很憂桑。
  (5)WWW.LoadFromCacheOrDownload一幀只會有一個bundle完成下載
    AssetBundle bundle = www.assetBundle;
    訪問www.assetBundle屬性就是同步從www中抽取並創建AssetBundle

  上述排版有點亂,點擊此處直接查看排版好的圖片格式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM