1. 程式人生 > >AssetBundle管理機制(下)

AssetBundle管理機制(下)

資源加載 應該 卸載 針對性 idt current ntc ims nor

◆◆

AssetBundle卸載

內存分析

技術分享

在上圖中的右側,我們列出了各種內存物件的卸載方式:

● 場景物件(GameObject):這類物件可通過Destroy函數進行卸載;

● 資源(包括Prefab):除了Prefab以外,資源文件可以通過三種方式來卸載:

1) 通過 Resources.UnloadAsset卸載指定的資源,CPU開銷小;

2) 通過Resources.UnloadUnusedAssets一次性卸載所有未被引用的資源,CPU開銷大;

3) 通過AssetBundle.Unload(true)在卸載AssetBundle對象時,將加載出來的資源一起卸載。

而對於Prefab,目前僅能通過DestroyImmediate來卸載,且卸載後,必須重新加載AssetBundle才能重新加載該Prefab。由於內存開銷較小,通常不建議進行針對性地卸載。

● WWW對象:調用對象的Dispose函數或將其置為null即可;

● WebStream:在卸載WWW對象以及對應的AssetBundle對象後,這部分內存即會被引擎自動卸載;

● SerializedFile:卸載AssetBundle後,這部分內存會被引擎自動卸載;

● AssetBundle對象:AssetBundle的卸載有兩種方式:

1) 通過AssetBundle.Unload(false),卸載AssetBundle對象時保留內存中已加載的資源;

2) 通過AssetBundle.Unload(true),卸載AssetBundle對象時卸載內存中已加載的資源,由於該方法容易引起資源引用丟失,因此並不建議經常使用;

註意點

● 在通過AssetBundle.Unload(false)卸載AssetBundle對象後,如果重新創建該對象並加載之前加載過的資源到內存時,會出現冗余,即兩份相同的資源。

● 被腳本的靜態變量引用的資源,在調用Resources.UnloadUnusedAssets時,並不會被卸載,在Profiler中能夠看到其引用情況。

技術分享

◆◆

UWA推薦方案

通過以上的講解,相信您對AssetBundle的加載和卸載已經有了明確的了解。下面,我們將簡單地做一下API選擇上的推薦:

● 對於需要常駐內存的Bundle文件來說,優先考慮減小內存占用,因此對於存放非Prefab資源(特別是紋理)的Bundle文件,可以考慮使用WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile加載,從而避免WebStream常駐內存;而對於存放較多Prefab資源的Bundle,則考慮使用new WWW加載,因為這類Bundle用WWW.LoadFromCacheOrDownload加載時產生的SerializedFile可能會比new WWW產生的WebStream更大。

● 對於加載完後即卸載的Bundle文件,則分兩種情況:優先考慮速度(加載場景時)優先考慮流暢度(遊戲進行時)

1)加載場景的情況下,需要註意的是避免WWW對象的逐個加載導致的CPU空閑,可以考慮使用加載速度較快的WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile,但需要避免後續大量地進行Load資源的操作,引起IO開銷(可以嘗試直接LoadAll)。

2) 遊戲進行的情況下,則需要避免使用同步操作引起卡頓,因此可以考慮使用new WWW配合AssetBundle.LoadAsync來進行平滑的資源加載,但需要註意的是,對於Shader、較大的Texture等資源,其初始化操作通常很耗時,容易引起卡頓,因此建議將這類資源在加載場景時進行預加載。

● 只在Bundle需要加密的情況下,考慮使用CreateFromMemory,因為該接口加載速度較慢。

● 盡量避免在遊戲進行中調用Resources.UnloadUnusedAssets(),因為該接口開銷較大,容易引起卡頓,可嘗試使用Resources.Unload(obj)來逐個進行卸載,以保證遊戲的流暢度。

需要說明的是,以上內存管理較適合於Unity 5.3之前的版本。Unity引擎在5.3中對AssetBundle的內存占用進行一定的調整,目前我們也在進一步的學習和研究中。


以上即為我們這次為您帶來的AssetBundle管理機制,希望對您的項目研發有所幫助。我們會在後續技術文章通過大量的案例來進一步解釋AssetBundle的管理機制,敬請關註。

AssetBundle管理機制(下)