【Unity】AssetBundle的加載與卸載方式摘要

AssetBundle的加載與卸載方式摘要

文中Object和Asset兩個詞用的比較混亂,但是Unity的官方英文文檔裏就是不停地在用這兩個詞,所以這裏也沒有替換爲中文。


用於加載AssetBundle的API

  • AssetBundle.LoadFromFile[Async]()
    • 首選方法(在速度、磁盤使用和內存佔用方面都很高效)
    • 適用於從本地存儲加載未壓縮或LZ4壓縮的AssetBundle
    • 使用LZMA壓縮的AssetBundle會被解壓到內存中
    • 使用LZ4壓縮或未壓縮的AssetBundle會直接從磁盤讀取
  • AssetBundle.LoadFromStream[Async]()
    • 適用於從流式數據中加載AssetBundle
    • 使用LZMA壓縮的AssetBundle會被解壓到內存中
    • 使用LZ4壓縮或未壓縮的AssetBundle會直接從流數據中讀取
    • 加載過程中不能Dispose流式對象
  • UnityWebRequest[AssetBundle].GetAssetBundle()
    • 適用於從遠程下載AssetBundle
    • 能夠緩存已下載的AssetBundle以便重用
    • 緩存系統中的AssetBundle僅以文件名進行標識而不是使用URL
  • AssetBundle.LoadFromMemory[Async]()
    • 不推薦使用
    • 會產生AssetBundle的冗餘副本

方括號[]用來表示類或方法的其他版本,下同。


用於從AssetBundle中加載Asset的API

  • AssetBundle.LoadAsset[Async]()
    • 首選方法
    • 適用於加載AssetBundle中的單個Object
    • 當要加載AssetBundle中超過66%的Object時,考慮使用LoadAllAssets()方法
  • AssetBundle.LoadAllAssets[Async]()
    • 適用於一次性加載AssetBundle中的全部Object
    • 比多次調用LoadAsset()更快
  • AssetBundle.LoadAssetWithSubAssets[Async]()
    • 適用於從AssetBundle中加載含有多個嵌套Object的複合Asset
    • 如果要加載的Object都來自於同一Asset並且他們和很多不相關的其他Object放在同一AssetBundle內,那麼應該使用此方法

當Object被加載完成後,會調用它的Awake()方法,並在下一幀對Unity引擎可用。


用於查詢AssetBundle依賴的API

  • AssetBundleManifest.GetAllDependencies()
    • 返回被AssetBundle所直接和間接依賴的所有AssetBundle的名稱
  • AssetBundleManifest.GetDirectDependencies()
    • 返回被AssetBundle所直接依賴的AssetBundle的名稱

加載AssetBundle時不能自動加載該AssetBundle所依賴的其他AssetBundle,但從AssetBundle中加載Asset時能夠自動加載該Asset所依賴的其他Asset。

AssetBundle和其所依賴的AssetBundle的加載順序並不重要,只要在從其中加載Asset時保證被依賴的AssetBundle已經加載即可。


用於卸載AssetBundle的API

  • AssetBundle.Unload()
    • 卸載此AssetBundle
    • 如果參數unloadAllLoadedObjects傳入false
      • 此AssetBundle中的Asset的壓縮數據文件將被卸載
      • 無法再從此AssetBundle中加載任何Object
      • 已經從此AssetBundle中加載的Object仍能正常工作
    • 如果參數unloadAllLoadedObjects傳入true
      • 首選方式
      • 所有從此AssetBundle中加載的Object都將被銷燬
      • Scene中對這些Object的引用將會丟失
  • AssetBundle.UnloadAllAssetBundles()
    • 卸載當前已加載的所有AssetBundle
    • 參數作用與AssetBundle.Unload()方法的參數相同
  • Resources.UnloadUnusedAssets()
    • 卸載所有未被使用的Asset

Asset的清理會在特定時期觸發,但也可以手動觸發。

當從AssetBundle中加載的Object被從活動的Scene中移除時,Unity不會自動將其卸載。

卸載AssetBundle但不卸載從其中加載的Object將會破壞此AssetBundle與Object之間的鏈接關係。如果之後再次加載了此AssetBundle並加載同一Object,內存中就會產生新的Object副本,而不是使用未被卸載的那個Object。

最好將那些需要同時加載或者更新的Object打包到同一個AssetBundle中。


Asset分配策略

  • AssetBundle太少
    • 增加運行時內存佔用
    • 增加加載時間
    • 需要下載的內容更大
  • AssetBundle太多
    • 增加構建時間
    • 使開發更復雜
    • 增加整體下載時間
  • 分組Object的基本策略
    • 根據邏輯實體分組
    • 根據Object類型分組
    • 根據同時使用的內容分組
  • 選擇AssetBundle壓縮方式時需要考慮的問題
    • 加載時間:從本地加載未壓縮的AssetBundle要比加載壓縮過的AssetBundle快得多
    • 構建時間:LZMA和LZ4壓縮文件的速度非常慢
    • 應用大小:如果AssetBundle被附帶在項目中,將它們壓縮可以減小應用程序的體積
    • 內存佔用:如果考慮內存佔用量,請使用不壓縮或者以LZ4壓縮的AssetBundle
    • 下載時間:如果AssetBundle很大或者用戶網絡帶寬有限,那可能需要壓縮
    • 如果AssetBundle中的主要內容是使用緊密壓縮算法進行壓縮的DXT壓縮紋理,那麼這個AssetBundle不應該再被壓縮
    • 強烈建議開發者不要在WebGL項目中使用壓縮的AssetBundle

AssetBundle補丁更新

使用AssetBundle進行補丁更新只需簡單的使用新AssetBundle替換已有的AssetBundle即可。如果正在使用UnityWebRequest[AssetBundle]管理應用程序的AssetBundle緩存,那麼傳遞一個不同的version參數即可觸發下載新的AssetBundle。

補丁系統需要維護兩個信息列表:

  • 含有當前已下載的AssetBundle及其版本信息的列表
  • 含有服務器上的AssetBundle及其版本信息的列表

補丁系統應該下載服務器上的AssetBundle的信息,然後與本地的AssetBundle信息進行比對,重新下載缺失的和版本信息發生變化的AssetBundle。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章