1. AssetBundle原理
AssetBundle是Unity中的一種資源包郊尝,這種資源包可以是游戲內(nèi)要用到的幾乎所有資源,例如:模型粗悯、紋理虚循、預(yù)設(shè)、場景等大部分文件更新样傍,并且可以在運(yùn)行時(shí)動(dòng)態(tài)加載横缔。
值得注意的是AssetBundle是可以多個(gè)文件一起打包,例如將要打包的資源做成預(yù)設(shè)后再進(jìn)行打包衫哥,這樣可以將預(yù)設(shè)上面附帶的組件茎刚、紋理、子對象等一并打包撤逢,加載后直接實(shí)例化就能直接使用了(并不是建議大家這么做膛锭,因?yàn)樯婕暗募y理材質(zhì)可能會(huì)造成資源冗余)。
另外AssetBundle 可以選擇壓縮后再進(jìn)行網(wǎng)絡(luò)傳輸蚊荣,提升傳輸效率初狰,減少包體大小等,不同的壓縮方式互例,我們放后面對比一下優(yōu)劣奢入。
那么使用AssetBundle可以解決的問題是:
1.1 實(shí)現(xiàn)資源的熱更。
1.2 減少初始包體大小媳叨,游戲可以做分包處理腥光。
1.3 ?可以利用二進(jìn)制文件做資源加密。
2. AssetBundle壓縮
以下我僅作 lzma和lz4的壓縮測試結(jié)果進(jìn)行總結(jié)糊秆,未壓縮和自定義在此暫不作比較武福。
2.1 文件大小和下載速度。lzma的壓縮大小比lz4小痘番,所以下載的速度lzma也比lz4的速度要快捉片。
2.2?加載開銷。運(yùn)行時(shí)加載開銷lz4要優(yōu)于lzma不少。
2.3?加載時(shí)內(nèi)存占用界睁。在使用LoadFromFile(Async)加載lzma格式的AB包時(shí)觉增,內(nèi)存的占用會(huì)是資源文件內(nèi)存的大約2倍兵拢,而使用lz4則是跟資源文件內(nèi)存大小一致的翻斟。
總結(jié)是lz4無論是解壓時(shí)間、加載開銷和內(nèi)存占用都優(yōu)于lzma说铃,但唯一的缺點(diǎn)就是包體會(huì)大不少(約25%)左右访惜。所以如果想要包體小,且加載速度又快腻扇,我們可以使用GZip把資源在打包完之后再打個(gè)壓縮包债热,這樣的話包體也會(huì)小很多。
3. AssetBundle加載
我們從幾種AssetBundle本地加載進(jìn)行比較?new www幼苛,AssetBundle.LoadFromFile對其優(yōu)劣進(jìn)行分析比較窒篱。
3.1 new www 其優(yōu)點(diǎn)是即可網(wǎng)絡(luò)加載又可加載本地,而其缺點(diǎn)是這種方式加載資源舶沿,所占的內(nèi)存要比LoadFromFiles高墙杯,相比LoadFromFile加載速度也會(huì)要慢一些。
3.2?AssetBundle.LoadFromFiles是目前版本最推薦的加載本地AssetBundle的方式括荡,從性能上目前是最好的高镐,內(nèi)存占用相比new www也要小。(本地加載www沒有可比性)
綜上所述畸冲,推薦大家使用www來下載由多個(gè)AB包壓縮生成的壓縮包嫉髓,下載然后解壓到本地后再通過LoadFromFile來加載,這樣的做法又快又高效邑闲,資源還小算行。
4. AssetBundle卸載
AssetBundle在使用過程中很容易產(chǎn)生卸載不干凈,繼而導(dǎo)致資源的冗余苫耸,強(qiáng)行卸載又可能導(dǎo)致資源丟失引用州邢。如何卸載AssetBundle是值得深入研究的一件事。
4.1?AssetBundle.Unload(false)鲸阔。?參數(shù)為false時(shí)偷霉,AssetBundle內(nèi)的序列化數(shù)據(jù)會(huì)被釋放,實(shí)例化的物體還都保持完好褐筛。簡單的說就是斷開了AssetBundle和實(shí)例之間的聯(lián)系类少。值得注意的是這樣做并不會(huì)卸載AssetBundle,意思是AssetBundle還會(huì)繼續(xù)占用內(nèi)存渔扎。然而如果再次實(shí)例化對象硫狞,也不會(huì)返回以前初例化過的AssetBundle,而是重新實(shí)例化一個(gè)新的AssetBundle,那么這樣就出現(xiàn)了冗余残吩,同樣的資源财忽,內(nèi)存中會(huì)出現(xiàn)多份。所以適合這樣來卸載的資源泣侮,一定是不需要多次創(chuàng)建實(shí)例的資源即彪,例如:一次性使用的配置信息。而卸載的話要當(dāng)創(chuàng)建的實(shí)例刪除回收以后活尊,手動(dòng)調(diào)用Resources.UnloadUnusedAssets或切換場景來釋放隶校。
4.2?AssetBundle.Unload(true)。參數(shù)為true時(shí)蛹锰,就簡單多了深胳,卸載AssetBundle,并且刪除被引用的資源铜犬。注意舞终!如果AssetBundle中有資源在場景中被引用,則會(huì)出現(xiàn)資源丟失的情況癣猾。這種卸載方式敛劝,最為徹底,完全從內(nèi)存移除煎谍,缺點(diǎn)是你需要一套機(jī)制攘蔽,來關(guān)注是不是還有資源引用,會(huì)不會(huì)引起異常呐粘。
4.3 關(guān)于卸載資源中满俗,必須要跟大家說明的是,加載的AssetBundle作岖,可以通過Resources.UnloadUnusedAssets來釋放唆垃。但是前提是加載的AssetBundle一定要先釋放干凈,即沒有任何引用痘儡。在調(diào)用AssetBundle.Unload(true)后會(huì)強(qiáng)行刪除創(chuàng)建的實(shí)例和引用辕万;而AssetBundle.Unload(false),必須先手動(dòng)刪除資源的實(shí)例和引用才能釋放沉删。另外Resources.UnloadUnusedAssets的開銷其實(shí)并不薪ツ颉(因?yàn)椴粌H僅是釋放AssetBundle還包括Resources.Load的其他資源),建議每隔一段時(shí)間進(jìn)行調(diào)用比較合適矾瑰。
那么給大家總結(jié)下使用卸載方案吧砖茸。
AssetBundle.Unload(false)適用于一次性使用的資源,獲得資源引用后直接調(diào)用殴穴,當(dāng)刪除引用后凉夯,下次調(diào)用Resources.UnloadUnusedAssets后就刪除了货葬。AssetBundle.Unload(true)在使用中,最好的做法是給創(chuàng)建出來的實(shí)例都添加計(jì)數(shù)劲够,當(dāng)計(jì)數(shù)不為0時(shí)震桶,表示場景或代碼中仍有引用,而當(dāng)計(jì)數(shù)為0時(shí)征绎,表示沒有引用了蹲姐,這樣就可以放心大膽的AssetBundle.Unload(true)了。
5. AssetBundle依賴打包注意事項(xiàng)
依賴打包最需要注意的也是唯一要注意的就是要避免依賴的處理不當(dāng)炒瘸,而導(dǎo)致資源冗余淤堵。
5.1 對于引用的資源,必須明確出現(xiàn)在其他AssetBundle的資源列表中顷扩,Unity才能識(shí)別為依賴關(guān)系,形成依賴打包慰毅。
5.2?合理規(guī)劃AssetBundle包隘截,公共的資源單獨(dú)抽離打包。
5.3?注意資源與AssetBundle的關(guān)系汹胃,一個(gè)AssetBundle可以包含多個(gè)資源婶芭,但同一份資源不允許存在于多個(gè)AssetBundle中。
6. AssetBundle打包策略和建議
在打包之前首先要按照資源類型和邏輯進(jìn)行分組着饥,接下來我們討論下分組犀农,當(dāng)然這里只是討論如果要分組的情況,我們也可根據(jù)項(xiàng)目實(shí)際情況宰掉。
因?yàn)槊總€(gè)項(xiàng)目在AssetBundle分組情況有多種選擇呵哨,有些項(xiàng)目甚至選擇的是全顆粒化增量更新的模式轨奄。因此該小節(jié)暫不作建議和說明孟害。
7. AssetBundles瀏覽與檢測
要檢測資源是否冗余,推薦使用AssetBundles-Browser挪拟、UnityStudio挨务、disunity、UWA GOT等工具進(jìn)行檢測玉组。
8. AssetBundles 好用的開源庫
嗯赚哗,以下排名不分先后航徙,都是很好用的開源庫,不過一些特殊功能,例如:加密赊堪、AssetBundle差異合并、打包策略等喘帚,還需要根據(jù)具體的項(xiàng)目加以實(shí)現(xiàn)矾踱。
以上開源庫均可在github上搜到户辱。