Unity中的動態載入資源

2021-08-17 09:42:53 字數 4414 閱讀 1569

在unity 3d裡有兩種動態載入機制: 一是resources.load;   一是通過assetbundle;

其實兩者本質上沒有什麼區別。resources.load就是從乙個預設打程序式包裡的assetbundle裡載入資源,而一般assetbundle檔案需要你自己建立,執行時動態載入,可以指定路徑和**的。其實場景裡所有靜態的物件也有這麼乙個載入過程,只是unity後台替你自動完成了。

1.    assetbundles是什麼?

在一些大型的網路遊戲,或者載入比較多的一些場景時,如果要等待所有模型,貼圖等各種資源檔案載入完畢才能執行遊戲,對使用者將會是乙個很頭大的事情。所以就需要用到動態載入,即assetbundles。比如玩家在進入遊戲時先載入一些周圍的場景檔案,這樣不僅可以提高速度還可以減少記憶體資源的消耗。      

assetbundles 可以是任意型別的檔案只要是unity3d能識別的資源檔案格式,識別主要是以副檔名為準,比如.prefab等等。當然如果你想包含自定義的二進位制檔案,需要命名這些檔案為以".bytes"為字尾,unity將會把這些檔案導成textassets。

2.    creating assetbundles 建立資源包

有三個類方法可以用來構建資源包:

buildpipeline.buildassetbundle,

buildpipeline.buildstreamedsceneassetbundle

buildpipeline.buildassetbundleexplicitassetnames.

推薦使用www.loadfromcacheordownload

[csharp]view plain

copy

function start ()  

var myloadedassetbundle = www.assetbundle;  

var asset = myloadedassetbundle.mainasset;  

}  4.   loading and unloading objects from an assetbundle從資源包載入和解除安裝物件

assetbundle.load

assetbundle.loadasync

assetbundle.loadall

assetbundle.unload(flase)是釋放assetbundle檔案的記憶體映象,不包含load建立的asset記憶體物件。

assetbundle.unload(true)是釋放那個assetbundle檔案記憶體映象和並銷毀所有用load建立的asset記憶體物件。

5. instantiating objects from assetbundles 從資源包例項化物體

instantiate乙個prefab,是乙個對assets進行clone(複製)+引用結合的過程,gameobject transform 是clone是新生成的。其他mesh / texture / material / shader 等,這其中些是純引用的關係的,包括:texture和terraindata,還有引用和複製同時存在的,包括:mesh/material/physicmaterial。引用的asset物件不會被複製,只是乙個簡單的指標指向已經load的asset物件。

unity裡每個script都是乙個封閉的class定義而已,並沒有寫呼叫**,光class的定義指令碼是不會工作的。其實unity引擎就是那個呼叫**,clone乙個script asset等於new乙個class例項,例項才會完成工作。把他掛到unity主線程的呼叫鏈裡去,class例項裡的onupdate onstart等才會被執行。多個物體掛同乙個指令碼,其實就是在多個物體上掛了那個指令碼類的多個例項而已,這樣就好理解了。在new class這個過程中,資料區是複製的,**區是共享的,算是一種特殊的複製+引用關係。

當你destroy乙個例項時,只是釋放那些clone物件,並不會釋放引用物件和clone的資料來源物件,destroy並不知道是否還有別的object在引用那些物件。等到沒有任何遊戲場景物體在用這些assets以後,這些assets就成了沒有引用的游離資料塊了,是unusedassets了,這時候就可以通過resources.unloadunusedassets來釋放,destroy不能完成這個任務,assetbundle.unload(false)也不行,assetbundle.unload(true)可以但不安全,除非你很清楚沒有任何物件在用這些assets了。

[csharp]view plain

copy

string

url = 

"";  ienumerator start ()   

6. including scripts in assetbundles 在資源包中包含指令碼

資源包可以作為textassets包含指令碼但是不會實際執行**。如果想要在資源包包含用來執行應用程式的**,需要預先編譯,然後使用mono reflection class來載入(注意:reflection在ios平台不可用)。可以在任何版本的c#ide編輯器(如:monodevelop, visual studio)或者使用mono/.net 文件編輯器。

[csharp]view plain

copy

string

url = 

"";  ienumerator start ()   

乙個常見的錯誤:

從某個assetbundle裡load了乙個prefab並轉殖之:obj = instantiate (assetbundle1.load('myprefab」);

這個prefab比如是個npc,然後你不需要他的時候你用了:destroy(obj);你以為就釋放乾淨了。其實這時候只是釋放了clone物件,通過load載入的所有引用、非引用assets物件全都靜靜靜的躺在記憶體裡。這種情況應該在destroy以後用:assetbundle1.unload(true),徹底釋放乾淨。如果這個assetbundle1是要反覆讀取的 不方便unload,那可以在destroy以後用:resources.unloadunusedassets()把所有和這個npc有關的asset都銷毀。

當然如果這個npc也是要頻繁建立 銷毀的那就應該讓那些assets呆在記憶體裡以加速遊戲體驗。由此可以解釋另乙個之前有人提過的話題:為什麼第一次instantiate乙個prefab的時候都會卡一下,因為在你第一次instantiate之前,相應的asset物件還沒有被建立,要載入系統內建的assetbundle並建立assets,第一次以後你雖然destroy了,但prefab的assets物件都還在記憶體裡,所以就很快了。

資源載入和釋放例子:

從磁碟讀取乙個1.unity3d檔案到記憶體並建立乙個assetbundle1物件

assetbundle assetbundle1 = assetbundle.createfromfile("1.unity3d");

從assetbundle1裡讀取並建立乙個texture asset,把obj1的主貼圖指向它

obj1.renderer.material.maintexture = assetbundle1.load("wall") as texture;

把obj2的主貼圖也指向同乙個texture asset

obj2.renderer.material.maintexture =obj1.renderer.material.maintexture;

texture是引用物件,永遠不會有自動複製的情況出現(除非你真需要,用**自己實現copy),只會是建立和新增引用

繼續:assetbundle1.unload(true) 那obj1和obj2都變成黑的了,因為指向的texture asset沒了

如果:assetbundle1.unload(false) 那obj1和obj2不變,只是assetbundle1的記憶體映象釋放了

繼續:destroy(obj1),//obj1被釋放,但並不會釋放剛才load的texture

如果這時候:

resources.unloadunusedassets();

不會有任何記憶體釋放 因為texture asset還被obj2用著

如果:destroy(obj2)

obj2被釋放,但也不會釋放剛才load的texture

繼續:resources.unloadunusedassets();

這時候剛才load的texture asset釋放了,因為沒有任何引用了

最後cg.collect();

強制立即釋放記憶體。

如何載入一堆大輪流顯示又不爆掉?

不考慮assetbundle,直接用www讀檔案的話等於是直接建立了乙個texture asset。

[csharp]view plain

copy

tllist<

string

> filelist;  

intn=0;  

ienumerator onclick()  

Unity動態載入資源的幾種方式

unity資源載入的幾種方式 instantiate 最簡單的一種方式,以例項化的方式動態生成乙個物體。assetsbundle 即將資源打成 asset bundle 放在伺服器或本地磁碟,然後使用www模組get 下來,然後從這個bundle中load某個object,unity官方推薦也是絕大...

Unity 資源載入

本地載入 不能載入ab包 object obj resources.load 資源名稱或路徑下的名字 不需要副檔名 t t1 resources.load 資源名稱或路徑下的名字 不需要副檔名 表示載入resources目錄下指定的資源 object objs resources.loadall 資...

Unity3D 動態載入資源

一 內部呼叫 1.resources.load path type 或resources.loadall path type 載入儲存在resources資料夾中path處的資源,必須忽略字尾名。gameobject instance instantiate resources.load enemy...