本周我們準備了兩篇 Unity/團結引擎常見問題 tips,均轉載自 Unity 社區大佬 ForgemasterGua,本篇主要解決 Addressable 的 Catalog 占用內存過大問題。ForgemasterGua 在 Unity 中國開發者社區持續更新技術內容中,點擊閱讀原文,前往 ForgemasterGua 的社區主頁,閱讀更多干貨文章。
初步分析問題
我們在使用 Addressable 管理 AssetBundle 打包和加載時,會用到目錄文件,也就是Catalog.json。 打開這個文件,可以看到其中包含了很多數據,包括打包了哪些 Asset、生成了哪些 AssetBundle 等。 其中最大的一塊數據是一個名字叫 “m_ExtraDataString” 的字符串。 我們遇到過 Catalog.json 文件本身就有 50 多 M,其中 m_ExtraDataString 就占 30 多 M 的情況。
這個數據加載進內存,對應的字符串甚至可以達到 70 多 M。
我們查看 Addressable 的源碼,可以在 ContentCatalogData.cs 文件的 SetData 函數里找到 m_ExtraDataString 的賦值。
而這里寫入的數據是在 AssetBundleProviders.cs 文件中的 AssetBundleRequestOptions,其中有 hash、crc、timeout、bundle name、bundle size 等很多關于一個 AssetBundle 的信息。
分析到這里,我們就不難理解:為什么隨著項目越來越大,AssetBundle 越來越多,Catalog 文件也會隨著越來越大,占用的內存也會越來越大了。
其實,Addressable 的官方文檔里也給出了有關的建議:
根據官方文檔的描述,AssetBundle 文件不宜過大或過小,如果每個 Asset 都單獨打包成一個 AssetBundle 文件,無疑是過小,會導致 Catalog 文件過大,占用內存也會很大的問題。
深入分析問題
到這里,我們可以很自然的想到,要解決這個問題,我們應當合理規劃 AssetBundle 的粒度,控制 AssetBundle 的大小和總數量在合理的范圍內。
具體到 Addressable 里,可以把同一個 Group 中的 Asset 一起打包。選擇 Bundle Mode 為 Pack Together 。
同時,Internal Asset Naming Mode 選擇 GUID 而不是文件的路徑,Bundle Naming Mode 選 Use Hash of Filename 也會減少 catalog.json 文件的大小。
Compress Catalog 選項,可以把 Catalog 從 Json 格式轉換成二進制格式,也能在一定程度上減小文件大小。
這些方法都能在一定程度上緩解這個問題。
但對于某些項目,要做到合理規劃 AssetBundle 的粒度是很難的,尤其是已經開發了很久很難重構的項目,我們就需要尋求其他解決方案。
開頭時我們提到過,m_ExtraDataString 數據占用的內存可以達到 70 多 M。它對應的數據結構是 AssetBundleRequestOptions。在 MemoryProfiler 中,我們除了能找到這塊 m_ExtraDataString 數據,也能找到根據這個字符串序列化好的數據結構。
我們可以看到這里有 33680 個 AssetBundle 文件,他們的 AssetBundleRequestOptions 一共占了 2.3 MB,不算大。
解決問題
我們最終需要的是這個只占 2.3M 的數據結構,至于占了 72MB 的字符串,只是序列化之前的數據。那么,我們能不能在得到了 AssetBundleRequestOptions 數據后,就釋放掉這塊 m_ExtraDataString 字符串的內存呢?
基于以上想法,我做了如下的嘗試:
通過Addressables.LoadContentCatalogAsync這個 API 加載 Catalog 文件后,就立刻釋放掉這個 OperationHandle。 這么做之后,我們重新抓取內存快照,我們依然能找到 AssetBundleRequestOptions 這塊內存,但 m_ExtraDataString 這塊內存已經沒有了。
通過這種方式,我們去掉了 catalog 以字符串形式存在的內存占用,保留了最終序列化好的數據部分。用 Addressable 官方例子 https://github.com/Unity-Technologies/Addressables-Sample 中的 Addressable Variants 工程 TextureScalerScene 驗證,這種方式沒有導致功能失常,內存占用也確實減少了。
Unity 官方微信
第一時間了解Unity引擎動向,學習進階開發技能
每一個“點贊”、“在看”,都是我們前進的動力
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.