Unity的AssetBundle使用總結

2021-10-01 14:56:10 字數 3137 閱讀 1532

assetbundle作為unity引擎的資源載入管理和熱更新手段,在各大專案內普遍的使用著。assetbundle使用方式簡單,只要設定assetbundlename,然後打包出檔案,在執行過程中載入就可以使用,但很多細節上的問題,會影響實際使用的效果。

之前我也寫過很多篇文章介紹assetbundle的使用和依賴拆分策略。這幾年來陸陸續續也做了不少專案,在裡面遇到了一些問題,所以想重新終結一下。

1、assetbundle的壓縮方式對比

2、assetbundle的依賴拆分策略

3、assetbundle的解除安裝策略

lzma:160mb

lz4:219mb

可以看出,用lz4打包出來的assetbundle,容量會比lzma的大30%左右,這個和網上看到的結論是相符合的。

但實際上這個容量的大小差別還是很有爭議性的,因為這裡面的資源全部都是prefab,沒有scene檔案。我之前的專案曾經試過lz4比lzma大了一倍多的,我暫時沒有很仔細的找出變大的資源是哪些,但那個專案使用的場景比較多,場景都是直接打包成assetbundle的,估計和這個有點關係。

2、載入速度:

以下通過同樣的載入方式來測試:

1.載入這個包含了所有模型的assetbundle,使用assetbundle.loadfromfile方法載入

2.使用loadasset方法讀取assetbundle內的乙個模型,並讓他例項化在場景裡面

首先是lzma壓縮方式的assetbundle:

在loadfromfile方法裡面,消耗了11909毫秒。

然後是lz4壓縮方式的assetbundle:

在loadfromfile方法裡面,消耗了84毫秒。

這兩者之間的差距已經非常明顯了,完全不是乙個數量級裡面的。

3、記憶體:

首先是在完全沒載入任何東西前,unity本身的記憶體截圖如下:

然後是載入lzma的assetbundle之後的記憶體:

最後是載入lz4的assetbundle之後的記憶體:

可以看出,lzma的assetbundle載入完之後,比lz4的assetbundle載入完的總記憶體增加了250mb左右。但是從單幀取樣來看,卻看不出他們之前的區別,只知道是unity本身占用的記憶體。

根據官方文件的說法lzma是乙個整體打成壓縮包。lz4是每個檔案單獨再打成壓縮包再放在一起。所以載入lz4的時候,assetbundle只是乙個引用,可以單獨的提取lz4壓縮包裡面的個別檔案來使用。

而lzma作為乙個整體,必須一起載入到記憶體裡面去。lzma載入完之後,是會解壓縮然後再次打包成lz4的格式存在於記憶體裡面,然後再載入的。

如果按照unity官方的這個說法,那麼lzma的載入速度慢,還有記憶體大,就是必然的事情了。

對比可以看出,lz4無論從載入速度還是記憶體方面都要比lzma好很多。唯一的缺點就是容量會大,具體比lzma大多少,這需要具體的情況去分析。

雖然lz4很多優點,但有些專案還是不能愉快的使用,因為對於買量遊戲來說,安裝包的包體大小決定了買量的成本,為了減少包體容量,研發團隊很有可能寧願犧牲效能來換取容量上的減少。這真是乙個可悲的現實。

基於這些問題,我並不建議載入完資源之後立刻解除安裝assetbundle。

我的思路是這樣的:

1、每乙個載入的assetbundle都受到管理,記錄每個assetbundle依賴了哪些assetbundle,並且記錄從單個assetbundle裡面loadasset過的所有資源。

2、每乙個載入出來的資源都可以判斷得到當前是否有被使用

3、找合適的時機檢查資源使用情況,如果乙個assetbundle裡面載入過的資源都沒有被使用,這個assetbundle本身又沒有被其他資源依賴著,那麼這個assetbundle就可以釋放。

這個流程下來,一般就能比較好的管理assetbundle和asset的使用和解除安裝了。但需要注意幾點潛規則:

1、在呼叫unloadunusedassets和system.gc.collect之後,如果立刻檢查弱引用,很有可能並沒有立刻判斷到物件已經被釋放。因為unloadunusedassets本身是乙個asyncoperation,是非同步的。所以需要隔一段時間判斷一次。

2、注意乙個gameobject被destroy之後,並不一定真正的被釋放掉了。假如這個gameobject是被某個類的變數引用著,就算gameobject被destroy了,但實際上只要引用他的物件一直不清空,當前的這段記憶體是不會釋放的。

這個問題其實很常發生,因為destroy了某個unity的gameobject之後,用**判斷某個引用這gameobject的變數時,的確可以判斷得到物件為空了。所以很多人在unity裡面寫**的時候,都不習慣清空儲存的變數。但其實可以做乙個實驗,我們可以寫乙個public的變數,然後把乙個gameobject賦予給他,最後把gameobject刪掉,回頭在inspector面板裡面看看,你會發現這個變數會變成missing,而不是none。missing的意思是,這裡引用的guid不為空,但引用的具體值可能找不到了。

3、如果決定要使用弱引用來判斷資源,就不要再用其他**把資源存起來了,比如很多人會另外建立乙個管理類,先存起乙個資源,等別人再次請求的時候,直接返回這個資源用於例項化之類。而是應該用弱引用的物件來做這個事情。因為如果用其他**來存,那麼只要**不釋放,弱引用也就永遠判斷不到他有沒有真的沒被使用。而且弱引用本身就把這個資源存在target引數裡面,只要先判斷一下target是否為空,如果不為空就返回使用就可以了。如果弱引用裡面的資源被釋放了,就再在assetbundle裡面載入出來。

Unity打包載入場景(Assetbundle )

打包scene 我們可以把整個場景進行打包,因為移動平台不能更新指令碼,所以這個功能就會有所限制,我的建議是烘培場景,然後把多個場景可復用的物件移除,場景中只保留獨一無二的遊戲物件,然後再打包場景,執行遊戲時載入場景後,再動態的將之前移除的物件重新新增進來。menuitem custom edito...

Unity打包以及載入AssetBundle思路

1.通常把專案中用到的所有shader打到乙個ab包裡,在資源呼叫時首先載入所有shader,因為專案中很多資源引用了shader 2.把一些共同引用的資源打到同乙個包裡,比如uia用了materialc,uib也用了materialc,uia,uib還用到了texc,那麼我們把materialc,...

Unity 查詢unity內建資源的工具

大致步驟 1 找到unity所有預設體和材質資源 2 拿到這些資源的依賴檔案 3 找到所有 依賴檔案裡的 texture shader material sprite 3.1 拿到依賴檔案裡的預設體 載入出來 遍歷元件 3.2 拿到依賴檔案裡的material 載入出來 檢視shader 和貼圖 3...