資源描述:
《全面理解unity加載和內(nèi)存管理》由會(huì)員上傳分享,免費(fèi)在線(xiàn)閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫(kù)。
1、最近一直在和這些內(nèi)容糾纏,把心得和大家共享一下:Unity里有兩種動(dòng)態(tài)加載機(jī)制:一是Resources.Load,一是通過(guò)AssetBundle,其實(shí)兩者本質(zhì)上我理解沒(méi)有什么區(qū)別。Resources.Load就是從一個(gè)缺省打進(jìn)程序包里的AssetBundle里加載資源,而一般AssetBundle文件需要你自己創(chuàng)建,運(yùn)行時(shí)動(dòng)態(tài)加載,可以指定路徑和來(lái)源的。其實(shí)場(chǎng)景里所有靜態(tài)的對(duì)象也有這么一個(gè)加載過(guò)程,只是Unity后臺(tái)替你自動(dòng)完成了。詳細(xì)說(shuō)一下細(xì)節(jié)概念:AssetBundle運(yùn)行時(shí)加載:來(lái)自文件就用CreateFromFile(注意這種方
2、法只能用于standalone程序)這是最快的加載方法也可以來(lái)自Memory,用CreateFromMemory(byte[]),這個(gè)byte[]可以來(lái)自文件讀取的緩沖,www的下載或者其他可能的方式。其實(shí)WWW的assetBundle就是內(nèi)部數(shù)據(jù)讀取完后自動(dòng)創(chuàng)建了一個(gè)assetBundle而已Create完以后,等于把硬盤(pán)或者網(wǎng)絡(luò)的一個(gè)文件讀到內(nèi)存一個(gè)區(qū)域,這時(shí)候只是個(gè)AssetBundle內(nèi)存鏡像數(shù)據(jù)塊,還沒(méi)有Assets的概念。Assets加載:用AssetBundle.Load(同Resources.Load)這才會(huì)從Asset
3、Bundle的內(nèi)存鏡像里讀取并創(chuàng)建一個(gè)Asset對(duì)象,創(chuàng)建Asset對(duì)象同時(shí)也會(huì)分配相應(yīng)內(nèi)存用于存放(反序列化)異步讀取用AssetBundle.LoadAsync也可以一次讀取多個(gè)用AssetBundle.LoadAllAssetBundle的釋放:AssetBundle.Unload(flase)是釋放AssetBundle文件的內(nèi)存鏡像,不包含Load創(chuàng)建的Asset內(nèi)存對(duì)象。AssetBundle.Unload(true)是釋放那個(gè)AssetBundle文件內(nèi)存鏡像和并銷(xiāo)毀所有用Load創(chuàng)建的Asset內(nèi)存對(duì)象。一個(gè)Prefab
4、從assetBundle里L(fēng)oad出來(lái)里面可能包括:Gameobjecttransformmeshtexturematerialshaderscript和各種其他Assets。你Instantiate一個(gè)Prefab,是一個(gè)對(duì)Assets進(jìn)行Clone(復(fù)制)+引用結(jié)合的過(guò)程,GameObjecttransform是Clone是新生成的。其他mesh/texture/material/shader等,這其中些是純引用的關(guān)系的,包括:Texture和TerrainData,還有引用和復(fù)制同時(shí)存在的,包括:Mesh/material/Phy
5、sicMaterial。引用的Asset對(duì)象不會(huì)被復(fù)制,只是一個(gè)簡(jiǎn)單的指針指向已經(jīng)Load的Asset對(duì)象。這種含糊的引用加克隆的混合,大概是搞糊涂大多數(shù)人的主要原因。專(zhuān)門(mén)要提一下的是一個(gè)特殊的東西:ScriptAsset,看起來(lái)很奇怪,Unity里每個(gè)Script都是一個(gè)封閉的Class定義而已,并沒(méi)有寫(xiě)調(diào)用代碼,光Class的定義腳本是不會(huì)工作的。其實(shí)Unity引擎就是那個(gè)調(diào)用代碼,Clone一個(gè)scriptasset等于new一個(gè)class實(shí)例,實(shí)例才會(huì)完成工作。把他掛到Unity主線(xiàn)程的調(diào)用鏈里去,Class實(shí)例里的OnUpda
6、teOnStart等才會(huì)被執(zhí)行。多個(gè)物體掛同一個(gè)腳本,其實(shí)就是在多個(gè)物體上掛了那個(gè)腳本類(lèi)的多個(gè)實(shí)例而已,這樣就好理解了。在newclass這個(gè)過(guò)程中,數(shù)據(jù)區(qū)是復(fù)制的,代碼區(qū)是共享的,算是一種特殊的復(fù)制+引用關(guān)系。你可以再I(mǎi)nstantiate一個(gè)同樣的Prefab,還是這套mesh/texture/material/shader...,這時(shí)候會(huì)有新的GameObject等,但是不會(huì)創(chuàng)建新的引用對(duì)象比如Texture.所以你Load出來(lái)的Assets其實(shí)就是個(gè)數(shù)據(jù)源,用于生成新對(duì)象或者被引用,生成的過(guò)程可能是復(fù)制(clone)也可能是引用
7、(指針)當(dāng)你Destroy一個(gè)實(shí)例時(shí),只是釋放那些Clone對(duì)象,并不會(huì)釋放引用對(duì)象和Clone的數(shù)據(jù)源對(duì)象,Destroy并不知道是否還有別的object在引用那些對(duì)象。等到?jīng)]有任何游戲場(chǎng)景物體在用這些Assets以后,這些assets就成了沒(méi)有引用的游離數(shù)據(jù)塊了,是UnusedAssets了,這時(shí)候就可以通過(guò)Resources.UnloadUnusedAssets來(lái)釋放,Destroy不能完成這個(gè)任務(wù),AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚
8、沒(méi)有任何對(duì)象在用這些Assets了。配個(gè)圖加深理解:雖然都叫Asset,但復(fù)制的和引用的是不一樣的,這點(diǎn)被Unity的暗黑技術(shù)細(xì)節(jié)掩蓋了,需要自己去理解。關(guān)于內(nèi)存管理按照傳統(tǒng)的編程思維,最好的方法是:自己維