AssetBundle詳解與優化

1. AssetBundle原理

AssetBundle是Unity中的一種資源包,這種資源包可以是遊戲內要用到的幾乎所有資源,例如:模型、紋理、預設、場景等大部分文件更新,並且可以在運行時動態加載。

值得注意的是AssetBundle是可以多個文件一起打包,例如將要打包的資源做成預設後再進行打包,這樣可以將預設上面附帶的組件、紋理、子對象等一併打包,加載後直接實例化就能直接使用了(並不是建議大家這麼做,因爲涉及的紋理材質可能會造成資源冗餘)。

另外AssetBundle 可以選擇壓縮後再進行網絡傳輸,提升傳輸效率,減少包體大小等,不同的壓縮方式,我們放後面對比一下優劣。

那麼使用AssetBundle可以解決的問題是:

1.1 實現資源的熱更。

1.2 減少初始包體大小,遊戲可以做分包處理。

1.3 可以利用二進制文件做資源加密。

2. AssetBundle壓縮

以下我僅作 lzma和lz4的壓縮測試結果進行總結,未壓縮和自定義在此暫不作比較。

2.1 文件大小和下載速度。lzma的壓縮大小比lz4小,所以下載的速度lzma也比lz4的速度要快。

2.2 加載開銷。運行時加載開銷lz4要優於lzma不少。

2.3 加載時內存佔用。在使用LoadFromFile(Async)加載lzma格式的AB包時,內存的佔用會是資源文件內存的大約2倍,而使用lz4則是跟資源文件內存大小一致的。

總結是lz4無論是解壓時間、加載開銷和內存佔用都優於lzma,但唯一的缺點就是包體會大不少(約25%)左右。所以如果想要包體小,且加載速度又快,我們可以使用GZip把資源在打包完之後再打個壓縮包,這樣的話包體也會小很多。

3. AssetBundle加載

我們從幾種AssetBundle本地加載進行比較 new www,AssetBundle.LoadFromFile對其優劣進行分析比較。

3.1 new www 其優點是即可網絡加載又可加載本地,而其缺點是這種方式加載資源,所佔的內存要比LoadFromFiles高,相比LoadFromFile加載速度也會要慢一些。

3.2 AssetBundle.LoadFromFiles是目前版本最推薦的加載本地AssetBundle的方式,從性能上目前是最好的,內存佔用相比new www也要小。(本地加載www沒有可比性)

綜上所述,推薦大家使用www來下載由多個AB包壓縮生成的壓縮包,下載然後解壓到本地後再通過LoadFromFile來加載,這樣的做法又快又高效,資源還小。

4. AssetBundle卸載

AssetBundle在使用過程中很容易產生卸載不乾淨,繼而導致資源的冗餘,強行卸載又可能導致資源丟失引用。如何卸載AssetBundle是值得深入研究的一件事。

4.1 AssetBundle.Unload(false)。 參數爲false時,AssetBundle內的序列化數據會被釋放,實例化的物體還都保持完好。簡單的說就是斷開了AssetBundle和實例之間的聯繫。值得注意的是這樣做並不會卸載AssetBundle,意思是AssetBundle還會繼續佔用內存。然而如果再次實例化對象,也不會返回以前初例化過的AssetBundle,而是重新實例化一個新的AssetBundle,那麼這樣就出現了冗餘,同樣的資源,內存中會出現多份。所以適合這樣來卸載的資源,一定是不需要多次創建實例的資源,例如:一次性使用的配置信息。而卸載的話要當創建的實例刪除回收以後,手動調用Resources.UnloadUnusedAssets或切換場景來釋放。

4.2 AssetBundle.Unload(true)。參數爲true時,就簡單多了,卸載AssetBundle,並且刪除被引用的資源。注意!如果AssetBundle中有資源在場景中被引用,則會出現資源丟失的情況。這種卸載方式,最爲徹底,完全從內存移除,缺點是你需要一套機制,來關注是不是還有資源引用,會不會引起異常。

4.3 關於卸載資源中,必須要跟大家說明的是,加載的AssetBundle,可以通過Resources.UnloadUnusedAssets來釋放。但是前提是加載的AssetBundle一定要先釋放乾淨,即沒有任何引用。在調用AssetBundle.Unload(true)後會強行刪除創建的實例和引用;而AssetBundle.Unload(false),必須先手動刪除資源的實例和引用才能釋放。另外Resources.UnloadUnusedAssets的開銷其實並不小(因爲不僅僅是釋放AssetBundle還包括Resources.Load的其他資源),建議每隔一段時間進行調用比較合適。

那麼給大家總結下使用卸載方案吧。

AssetBundle.Unload(false)適用於一次性使用的資源,獲得資源引用後直接調用,當刪除引用後,下次調用Resources.UnloadUnusedAssets後就刪除了。AssetBundle.Unload(true)在使用中,最好的做法是給創建出來的實例都添加計數,當計數不爲0時,表示場景或代碼中仍有引用,而當計數爲0時,表示沒有引用了,這樣就可以放心大膽的AssetBundle.Unload(true)了。

5. AssetBundle依賴打包注意事項

依賴打包最需要注意的也是唯一要注意的就是要避免依賴的處理不當,而導致資源冗餘。

5.1 對於引用的資源,必須明確出現在其他AssetBundle的資源列表中,Unity才能識別爲依賴關係,形成依賴打包。

5.2 合理規劃AssetBundle包,公共的資源單獨抽離打包。

5.3 注意資源與AssetBundle的關係,一個AssetBundle可以包含多個資源,但同一份資源不允許存在於多個AssetBundle中。

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