【轉(zhuǎn)】Unity資源機(jī)制

原文地址:http://gad.qq.com/article/detail/7180936
作者:Loki+X
Unity資源機(jī)制
1、概述
  本文意在闡述Unity資源機(jī)制相關(guān)的信息,以及一些關(guān)于個(gè)人的理解與試驗(yàn)結(jié)果。另外還會(huì)提及一些因機(jī)制問題可能會(huì)出現(xiàn)的異常以及處理建議。大部分機(jī)制信息來源于官方文檔,另外為自我驗(yàn)證后的結(jié)果。

2、資源
概述
   Unity必須通過導(dǎo)入將所支持的資源序列化,生成AssetComponents后,才能被Unity使用。以下是Unity對(duì)Assets的描述:
  Assets are the models,textures,sounds and all other “content”files from which you make your game。
  資源(Asset)是硬盤中的文件,存儲(chǔ)在Unity工程的Assets文件夾內(nèi)。有些資源的數(shù)據(jù)格式是Unity原聲支持的,有些資源則需要轉(zhuǎn)換為源生的數(shù)據(jù)格式后才能被使用。
  對(duì)象(UnityEngine.Object),代表序列化數(shù)據(jù)的集合,表示某個(gè)資源的具體實(shí)例。它可以是Unity使用的任何類型的資源,所有對(duì)象都是UnityEngine.Object基類的子類
  資源與對(duì)象時(shí)一對(duì)多的關(guān)系。

名稱 描述 支持格式
Audio Clip 音頻剪輯 音頻:.aif .wav .mp3 .ogg音軌:.xm .mod .it .s3m
Cubemap Texture 立方體貼圖紋理
Flare 耀斑
Font 字體 .ttf
Material 材質(zhì)
Meshes 網(wǎng)格 .FBX .dae .3DS .dxf .obj
Movie Texture 電影貼圖 .mov .mpg .mpeg .mp4 .avi .asf (導(dǎo)入需要QuickTime)
Procedural Material Assets 程序材質(zhì)資源
Render Texture 渲染紋理
Text Asset 文本資源 .txt .html .htm .xml .bytes
Texture 2D 二維紋理 PSD TIFF JPG TGA PNG GIF BMP IFF PICT

除此之外,想使用Unity不支持導(dǎo)入,或者未經(jīng)導(dǎo)入的資源,只能使用IO Stream或者WWW 方法,這些將在下文對(duì)應(yīng)欄目中說明。
  注意:AssetBundle不是資源組件,故無法用資源組件的方式載入,只能使用WWW或者AssetBundle相關(guān)接口載入與讀取

GUID與fileID(本地ID)
  Unity會(huì)為每個(gè)導(dǎo)入到Assets目錄中的資源創(chuàng)建一個(gè)meta文件,文件中記錄了GUID,GUID用來記錄資源之間的引用關(guān)系。還有fileID(本地ID),用于標(biāo)識(shí)資源內(nèi)部的資源。資源間的依賴關(guān)系通過GUID來確定;資源內(nèi)部的依賴關(guān)系使用fileID來確定。

InstanceID(實(shí)例ID)
  Unity為了在運(yùn)行時(shí),提升資源管理的效率,會(huì)在內(nèi)部維護(hù)一個(gè)緩存表,負(fù)責(zé)將文件的GUID與fileID轉(zhuǎn)換成為整數(shù)數(shù)值,這個(gè)數(shù)值在本次會(huì)話中是唯一的,稱作實(shí)例ID(InstanceID)。
  程序啟動(dòng)時(shí),實(shí)例ID緩存與所有工程內(nèi)建的對(duì)象(例如在場(chǎng)景中被引用),以及Resource文件夾下的所有對(duì)象,都會(huì)被一起初始化。如果在運(yùn)行時(shí)導(dǎo)入了新的資源,或從AssetBundle中載入了新的對(duì)象,緩存會(huì)被更新,并為這些對(duì)象添加相應(yīng)條目。實(shí)例ID僅在失效時(shí)才會(huì)被從緩存中移除,當(dāng)提供了指定文件GUID和fileID的AssetBundle被卸載時(shí)會(huì)產(chǎn)生移除操作。
  卸載AssetBundle會(huì)使實(shí)例ID失效,實(shí)例ID與其文件GUID和fileID之間的映射會(huì)被刪除以便節(jié)省內(nèi)存。重新載入AssetBundle后,載入的每個(gè)對(duì)象都會(huì)獲得新的實(shí)例ID。

** 資源的生命周期**
  Object從內(nèi)存中加載或卸載的時(shí)間點(diǎn)是定義好的。Object有兩種加載方式:自動(dòng)加載與外部加載。當(dāng)對(duì)象的實(shí)例ID與對(duì)象本身解引用,對(duì)象當(dāng)前未被加載到內(nèi)存中,而且可以定位到對(duì)象的源數(shù)據(jù),此時(shí)對(duì)象會(huì)被自動(dòng)加載。對(duì)象也可以外部加載,通過在腳本中創(chuàng)建對(duì)象或者調(diào)用資源加載API來載入對(duì)象(例如:AssetBundle.LoadAsset)
對(duì)象加載后,Unity會(huì)嘗試修復(fù)任何可能存在的引用關(guān)系,通過將每個(gè)引用文件的GUID與FileID轉(zhuǎn)化成實(shí)例ID的方式。一旦對(duì)象的實(shí)例ID被解引用且滿足以下兩個(gè)標(biāo)準(zhǔn)時(shí),對(duì)象會(huì)被強(qiáng)制加載:
  實(shí)例ID引用了一個(gè)沒有被加載的對(duì)象。
  實(shí)例ID在緩存中存在對(duì)應(yīng)的有效GUID和本地ID。
  如果文件GUID和本地ID沒有實(shí)例ID,或一個(gè)已卸載對(duì)象的實(shí)例ID引用了非法的文件GUID和本地ID,則引用本身會(huì)被保留,但實(shí)例對(duì)象不會(huì)被加載。在Unity編輯器中表現(xiàn)為空引用,在運(yùn)行的應(yīng)用中,或場(chǎng)景視圖里,空對(duì)象會(huì)以多種方式表示,取決于丟失對(duì)象的類型:網(wǎng)格會(huì)變得不可見,紋理呈現(xiàn)為紫紅色等等。

** MonoScripts**
  一個(gè)MonoScripts含有三個(gè)字符串:程序庫名稱,類名稱,命名空間。
構(gòu)建工程時(shí),Unity會(huì)收集Assets文件夾中獨(dú)立的腳本文件并編譯他們,組成一個(gè)Mono程序庫。Unity會(huì)將Assets目錄中的語言分開編譯,Assets/Plugins目錄中的腳本同理。Plugin子目錄之外的C#腳本會(huì)放在Assembly-CSharp.dll中。而Plugin及其子目錄中的腳本則放置在Assembly-CSharp-firstpass.all中。
這些程序庫會(huì)被MonoScripts所引用,并在程序第一次啟動(dòng)時(shí)被加載。

3、資源文件夾
** Assets**
  為Unity編輯器下的資源文件夾,Unity項(xiàng)目編輯時(shí)的所有資源都將置入此文件夾內(nèi)。在編輯器下,可以使用以下方法獲得資源對(duì)象:
  AssetDatabase.LoadAssetAtPath("Assets/x.txt");
  注意:此方法只能在編輯器下使用,當(dāng)項(xiàng)目打包后,在游戲內(nèi)無法運(yùn)作。參數(shù)為包含Assets內(nèi)的文件全路徑,并且需要文件后綴。
  Assets下的資源除特殊文件夾內(nèi),或者在會(huì)打入包內(nèi)的場(chǎng)景中引用的資源,其余資源不會(huì)被打入包中。

Resources
資源載入
  Assets下的特殊文件夾,此文件夾內(nèi)的資源將會(huì)在項(xiàng)目打包時(shí),全部打入包內(nèi),并能通過以下方法獲得對(duì)象:
  Resources.Load("fileName");
  Resources.Load("fileName");
  注意:函數(shù)內(nèi)的參數(shù)為相對(duì)于Resource目錄下的文件路徑與名稱,不包含后綴。Assets目錄下可以擁有任意路徑及數(shù)量的Resources文件夾,在運(yùn)行時(shí),Resources下的文件路徑將被合并。
  例:Assets/Resources/test.txt與 Assets/TestFloder/Resources/test.png在使用Resource.Load("test")載入時(shí),將被視為同一資源,只會(huì)返回第一個(gè)符合名稱的對(duì)象。如果使用Resource.Load(“test”)將返回text.txt;
  如果在Resources下有相同路徑及名稱的資源,使用以上方法只能獲得第一個(gè)符合查找條件的對(duì)象,使用以下方法能或得到所有符合條件的對(duì)象:
Object[] assets = Resources.LoadAll("fileName");
TextAsset[] assets = Resources.LoadAll("fileName");

** 相關(guān)機(jī)制**
  在工程進(jìn)行打包后,Resource文件夾中的資源將進(jìn)行加密與壓縮,打包后的程序內(nèi)將不存在Resource文件夾,故無法通過路徑訪問以及更新資源。
  依本文2.3章節(jié)所述,在程序啟動(dòng)時(shí)會(huì)為Resource下的所有對(duì)象進(jìn)行初始化,構(gòu)建實(shí)例ID。隨著Resource內(nèi)資源的數(shù)量增加,此過程耗時(shí)的增加是非線性的。故會(huì)出現(xiàn)程序啟動(dòng)時(shí)間過長(zhǎng)的問題,請(qǐng)密切留意Resource內(nèi)的資源數(shù)量。

卸載資源
  所有實(shí)例化后的GameObject 可以通過Destroy函數(shù)銷毀。請(qǐng)留意Object與GameObject之間的區(qū)別與聯(lián)系
Object可以通過Resources中的相關(guān)Api進(jìn)行卸載

Resources.UnloadAsset(Object);//卸載對(duì)應(yīng)Object 
Resources.UnloadUnusedAssets();//卸載所有沒有被引用以及實(shí)例化的Object 

注意以下情況:

Object obj = Resources.Load("MyPrefab"); 
GameObject instance = Instantiate(obj) as GameObjct; 
...... 
Destroy(instance); 
Resources.UnloadUnusedAssets(); 

此時(shí)UnloadUnusedAssets將不會(huì)生效,因?yàn)閛bj依然引用了MyPrefab,需要將obj = null,才可生效。


StreamingAssets
概述
  StreamingAssets文件夾為流媒體文件夾,此文件夾內(nèi)的資源將不會(huì)經(jīng)過壓縮與加密,原封不動(dòng)的打包進(jìn)游戲包內(nèi)。在游戲安裝時(shí),StreamAssets文件件內(nèi)的資源將根據(jù)平臺(tái),移動(dòng)到對(duì)應(yīng)的文件夾內(nèi)。StreamingAssets文件夾在Android與IOS平臺(tái)上為只讀文件夾.
  你可以使用以下函數(shù)獲得不同平臺(tái)下的StreamingAssets文件夾路徑:

Application.streamingAssetsPath 

請(qǐng)參考以下各平臺(tái)下StreamingAssets文件夾的等價(jià)路徑,Application.dataPath為程序安裝路徑。Android平臺(tái)下的路徑比較特殊,請(qǐng)留意此路徑的前綴,在一些資源讀取的方法中是不必要的(AssetBundle.LoadFromFile,下詳)
Application.dataPath+"/StreamingAssets"http://Windows OR MacOS
Application.dataPath+"/Raw" //IOS
"jar:file://"+Application.dataPath+"!/assets/" //Android

文件讀取
  StreamingAssets文件夾下的文件在游戲中只能通過IO Stream或者WWW的方式讀取(AssetBundle除外)
IO Stream方式

using(FileStream stream = File.Open(Application.streamingAssetsPath + "fileName", FileMode.Open)) 
{ 
    //處理方法 
} 

WWW方式(注意協(xié)議與不同平臺(tái)下路徑的區(qū)別)

using(WWW www = new WWW(Application.streamingAssetsPath + "fileName")) 
{ 
    yield return www; 
    www.text; 
    www.texture; 
}

AssetBundle特有的同步讀取方式(注意安卓平臺(tái)下的路徑區(qū)別)

string assetbundlePath = 
#if UNITY_ANDROID 
Application.dataPath+"!/assets"; 
#else 
Application.streamingAssetsPath; 
#endif  
AssetBundle.LoadFromFile(assetbundlePath+"/name.unity3d"); 

PersistentDataPath

Application.persistentDataPath 

Unity指定的一個(gè)可讀寫的外部文件夾,該路徑因平臺(tái)及系統(tǒng)配置不同而不同??梢杂脕肀4鏀?shù)據(jù)及文件。該目錄下的資源不會(huì)在打包時(shí)被打入包中,也不會(huì)自動(dòng)被Unity導(dǎo)入及轉(zhuǎn)換。該文件夾只能通過IO Stream以及WWW的方式進(jìn)行資源加載。

4、WWW載入資源
** 概述**
  WWW是一個(gè)Unity封裝的網(wǎng)絡(luò)下載模塊,支持Http以及file兩種URL協(xié)議,并會(huì)嘗試將資源轉(zhuǎn)換成Unity能使用的AssetsComponents(如果資源是Unity不支持的格式,則只能取出byte[])。具體對(duì)應(yīng)的格式參考第一章表格。WWW加載是異步方法。

byte[] bytes = WWW.bytes; 
string text = WWW.text; 
Texture2D texture = WWW.texture; 
MovieTexture movie = WWW.movie; 
AssetBundle assetbundle = WWW.assetBundle; 
AudioClip audioClip = WWW.audioClip; 

相關(guān)機(jī)制
** new WWW**
  每次new WWW時(shí),Unity都會(huì)啟用一個(gè)線程去進(jìn)行下載。通過此方式讀取或者下載資源,會(huì)在內(nèi)存中生成WebStream,WebStream為下載文件轉(zhuǎn)換后的內(nèi)容,占用內(nèi)存較大。使用WWW.Dispose將終止仍在加載過程中的進(jìn)程,并釋放掉內(nèi)存中的WebStream。
  如果WWW不及時(shí)釋放,將占用大量的內(nèi)存,推薦搭配using方式使用,以下兩種方式等價(jià)。

WWW www = new WWW(Application.streamingAssetsPath + "fileName"); 
try 
{ 
    yield return www; 
    www.text; 
    www.texture; 
} 
finally 
{ 
    www.Dispose(); 
} 
using(WWW www = new WWW(Application.streamingAssetsPath + "fileName")) 
{ 
    yield return www; 
    www.text; 
    www.texture; 
} 

如果載入的為Assetbundle且進(jìn)行過壓縮,則還會(huì)在內(nèi)存中占用一份AssetBundle解壓用的緩沖區(qū)Deompresion Buffer,AssetBundle壓縮格式的不同會(huì)影響此區(qū)域的大小。

WWW.LoadFromCacheOrDownload

int version = 1; 
WWW.LoadFromCacheOrDownload(PathURL+"/fileName",version); 

使用此方式加載,將先從硬盤上的存儲(chǔ)區(qū)域查找是否有對(duì)應(yīng)的資源,再驗(yàn)證本地Version與傳入值之間的關(guān)系,如果傳入的Version>本地,則從傳入的URL地址下載資源,并緩存到硬盤,替換掉現(xiàn)有資源,如果傳入Version<=本地,則直接從本地讀取資源;如果本地沒有存儲(chǔ)資源,則下載資源。此方法的存儲(chǔ)路徑無法設(shè)定以及訪問。使用此方法載入資源,不會(huì)在內(nèi)存中生成 WebStream(其實(shí)已經(jīng)將WebStream保存在本地),如果硬盤空間不夠進(jìn)行存儲(chǔ),將自動(dòng)使用new WWW方法加載,并在內(nèi)存中生成WebStream。在本地存儲(chǔ)中,使用fileName作為標(biāo)識(shí)符,所以更換URL地址而不更改文件名,將不會(huì)造成緩存資源的變更。
保存的路徑無法更改,也沒有接口去獲取此路徑

5、 AssetBundle
概述
  AssetBundles let you stream additional assets via the WWW class and instantiate them at runtime. AssetBundles are created via BuildPipeline.BuildAssetBundle.
  AssetBundle是Unity支持的一種文件儲(chǔ)存格式,也是Unity官方推薦的資源存儲(chǔ)與更新方式,它可以對(duì)資源(Asset)進(jìn)行壓縮,分組打包,動(dòng)態(tài)加載,以及實(shí)現(xiàn)熱更新,但是AssetBundle無法對(duì)Unity腳本進(jìn)行熱更新,因?yàn)槠湫枰诖虬鼤r(shí)進(jìn)行編譯。

Assetbundle打包
平臺(tái)兼容性
  AssetBundle適用于多種平臺(tái),但不同平臺(tái)所使用的AssetBundle并不相同,在創(chuàng)建AssetBundle時(shí)需要通過參數(shù)來指定目標(biāo)平臺(tái),其關(guān)系如下表

Standalone WebPlayer IOS Android
Standalone
WebPlayer
IOS
Android

創(chuàng)建API

public enum BuildAssetBundleOptions
{
    None = 0,
    //Build assetBundle without any special option. 
    UncompressedAssetBundle = 1,
    //Don't compress the data when creating the asset bundle. 
    CollectDependencies = 2,
    //Includes all dependencies. 
    CompleteAssets = 4,
    //Forces inclusion of the entire asset. 
    DisableWriteTypeTree = 8,
    //Do not include type information within the AssetBundle. 
    DeterministicAssetBundle = 16,
    //Builds an asset bundle using a hash for the id  
    ForceRebuildAssetBundle = 32,
    //Force rebuild the assetBundles. 
    IgnoreTypeTreeChanges = 64,
    //Ignore the type tree changes when doing the incremental build check. 
    AppendHashToAssetBundleName = 128,
    //Append the hash to the assetBundle name. 
    ChunkBasedCompression = 256
    //Use chunk-based LZ4 compression when creating the AssetBundle. 
}
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles("OutputPath", BuildAssetBundleOptions, tragetPlatform);

在Unity的5.3版本中,簡(jiǎn)化了AssetBundle的打包方式,只留下了一個(gè)api與寥寥幾個(gè)設(shè)置參數(shù),而之前最讓人頭痛的資源依賴管理,也被默認(rèn)進(jìn)行處理。 而在每個(gè)Asset文件的Inspector面板上都會(huì)多出一個(gè)Asset Labels的設(shè)定欄:

AssetBundle name:需要將此資源打包的AssetBundle名稱
  AssetBundle Variant:需要將此資源打包的AssetBundle的變體名

Variant
  Variant是5.3以后新添加的一個(gè)概念,這個(gè)值其實(shí)是一個(gè)尾綴,將添加在對(duì)應(yīng)AssetBundle的名稱之后,如:ddzgame.hd,hd就是Variant(從此以后AssetBundle的尾綴已經(jīng)跟其文件類型本身沒有任何聯(lián)系)。

自動(dòng)打包腳本
  從以上可知,如果需要一個(gè)一個(gè)的對(duì)資源設(shè)置AssetBundle Name與Variant實(shí)在太過繁瑣與麻煩,也可能出現(xiàn)紕漏,好在可以通過腳本去批量設(shè)置這兩個(gè)參數(shù):

AssetImporter assetImporter = AssetImporter.GetAtPath("path");
assetImporter.assetBundleName = "Assetbundle Name";
assetImporter.assetBundleVariant = "Assetbundle Variant";

其中path是資源在Assets目錄下的路徑。

Scene打包
  Scene打包跟資源打包無異,唯一需要注意的是:Scene只能與Scene打入同一個(gè)AssetBundle內(nèi),而無法與其他資源打入同一個(gè)AssetBundle。
  PS:AssetBundle內(nèi)的Scene需要在AssetBundle加載后,通過SceneManager來加載。

AssetBundle依賴
依賴機(jī)制
  假設(shè)有AssetBundleA與 AssetBundleB兩個(gè)AssetBundle,AssetBundle中的資源引用了AssetBundleB中的資源,則稱AssetBundleA依賴于AssetBundleB。具體實(shí)例請(qǐng)看下圖注意被依賴AssetBundle需要加載的時(shí)機(jī)

注意其依賴的機(jī)制: AssetBundle中保存有其中所有資源的GUID,FileID等序列化信息,AssetBundle只會(huì)在內(nèi)存中尋找其依賴資源所在的AssetBundle,并自動(dòng)從中加載出所需資源。具體可參考本文2.3章節(jié)

** Manifest**

在前面有提到,在5.3中,Unity會(huì)自動(dòng)處理AssetBundle中資源的依賴關(guān)系。在默認(rèn)情況下,如果AssetBundle間有交叉的資源引用,不會(huì)再重復(fù)打包,在打包AssetBundle后,會(huì)發(fā)現(xiàn)其在輸出目錄多出了一個(gè)與目錄名稱相同的無后綴AssetBundle文件,其為自動(dòng)生成的AssetBundleManifest文件,其內(nèi)保存有此次生成的所有AssetBundle之間的依賴關(guān)系與清單。我們可以在載入這個(gè)AssetBundle后使用以下方法獲得此對(duì)象。

AssetBundle.LoadAsset("AssetBundleManifest");

Manifest保存有重要的依賴信息,在載入AssetBundle時(shí),可以通過Manifest查詢其是否有依賴的AssetBundle,然后我們手動(dòng)對(duì)其進(jìn)行管理,避免依賴項(xiàng)丟失而出現(xiàn)bug
string[] fullnames = AssetBundle.GetDirectDependencies(fullname);
string[] fullnames = AssetBundle.GetAllDependencies(fullname);
  Direct方法會(huì)返回所有直接依賴的AssetBundle名稱數(shù)組,All方法會(huì)返回所有依賴的AssetBundle名稱數(shù)組,fullname包括名稱與Variant。推薦使用Direct方法做遞歸處理,避免重復(fù)載入。

AssetBundle加載
加載方式
  之前已經(jīng)提及,不再詳細(xì)說明,使用WWW 或者 AssetBundle相關(guān)API加載,其中AssetBundle的API只能進(jìn)行本地加載。

AssetBundle.LoadfromMemory(byte[] bytes)

此API是一個(gè)例外,用來對(duì)加密的Assetbundle進(jìn)行讀取,可以結(jié)合WWW使用。

壓縮
  LZMA(Ziv-Markov chain algorithm)格式
  Unity打包成AssetBundle時(shí)的默認(rèn)格式,會(huì)將序列化數(shù)據(jù)壓縮成LZMA流,使用時(shí)需要整體解包。優(yōu)點(diǎn)是打包后體積小,缺點(diǎn)是解包時(shí)間長(zhǎng),且占用內(nèi)存。

LZ4格式
  5.3新版本添加的壓縮格式,壓縮率不及LZMA,但是不需要整體解壓。LZ4是基于chunk的算法,加載對(duì)象時(shí)只有響應(yīng)的chunk會(huì)被解壓。
  壓縮格式在打包時(shí)通過AssetBundleOption參數(shù)選擇。

內(nèi)存占用

AssetBundle加載后會(huì)在內(nèi)存中生成AssetBundle的序列化架構(gòu)的占用,一般來說遠(yuǎn)遠(yuǎn)小于資源本身,除非包含復(fù)雜的序列化信息(復(fù)雜多層級(jí)關(guān)系或復(fù)雜靜態(tài)數(shù)據(jù)的prefab等)


AssetBundle卸載
卸載API

AssetBundle.Unload(bool unloadAllLoadedObjects);

AssetBundle只有唯一的一個(gè)卸載函數(shù),傳入的參數(shù)用來選擇是否將已經(jīng)從此AssetBundle中加載的資源一起卸載。另外,已經(jīng)從AssetBundle中加載的資源可以通過Resources.UnloadAsset(Object)卸載。如果想通過Resources.UnloadUnusedAssets()卸載從AssetBundle加載的資源,一定要先將AssetBundle卸載后才能生效。

資源卸載總覽

內(nèi)存關(guān)系圖

當(dāng)AssetBundle被卸載后,實(shí)例ID與其文件GUID和本地ID之間的映射會(huì)被刪除, 即其無法被其后加載的依賴于它的資源所查找及引用。詳情請(qǐng)參考本文2.3章節(jié)

** 案例分析**
  案例1 游戲切換到后臺(tái)一段時(shí)候切回,出現(xiàn)shader或者Texture丟失。
  在移動(dòng)平臺(tái),當(dāng)程序切到主界面或者在后臺(tái)長(zhǎng)時(shí)間運(yùn)行時(shí),GPU會(huì)自動(dòng)對(duì)后臺(tái)程序的資源進(jìn)行清理。如果shader或者Texture是從AssetBundle中加載出來,而此AssetBundle已經(jīng)被卸載的話,Unity無法在程序恢復(fù)時(shí)從內(nèi)存中加載這些資源,從而造成丟失。有人會(huì)問,這些資源不是已經(jīng)加載到內(nèi)存中了么?但是,他們?cè)诒患虞d到GPU之后會(huì)被從內(nèi)存中清除。因此要防止此狀況最穩(wěn)健的方法,就是在場(chǎng)景切換前,不要卸載掉其所屬的AssetBundle。
  案例2 當(dāng)經(jīng)常使用AssetBundleB.Unload(false)卸載時(shí),有時(shí)會(huì)發(fā)現(xiàn)AssetBundle中的資源在內(nèi)存中有多份同時(shí)存在。
  問題的根源在于從AssetBundle中加載出來的資源,在該AssetBundle卸載之后與其的聯(lián)系就斷開了。

例如:從AssetBundleA中加載出來一個(gè)Prefab p1,p1依賴資源tex1也會(huì)自動(dòng)加載到內(nèi)存中。然后用AssetBundle.Unload(false)卸載AssetBundleA,此時(shí)p1與AssetBundleA的聯(lián)系斷開。之后,從AssetBundleA中加載Prefab p2,p2也依賴資源tex1,那么在加載p2時(shí)tex1會(huì)再次被加載到內(nèi)存中,導(dǎo)致重復(fù)。

原文地址:http://gad.qq.com/article/detail/7180936
作者:Loki+X

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 翻譯:莫銘原文地址:AssetBundle usage patterns 本系列中的上一篇文章覆蓋了AssetBu...
    莫銘閱讀 5,652評(píng)論 1 12
  • 這部分主要討論了AssetBundle的如下知識(shí): AssetBundle的基礎(chǔ)知識(shí) 使用AssetBundle的...
    Wenchao閱讀 1,805評(píng)論 0 5
  • 這一部分主要是對(duì)Unity的Resources系統(tǒng)和AssetBundle系統(tǒng)進(jìn)行深入討論。 分為四個(gè)部分: 有關(guān)...
    Wenchao閱讀 2,171評(píng)論 0 1
  • 1、什么是AssetBundle AssetBundle 是Unity pro提供的一種用來存儲(chǔ)資源的文件格式,它...
    好怕怕閱讀 7,850評(píng)論 1 8
  • 我只想做個(gè)夜半的歌者, 夜色里流淌出款款深情。 溫潤的風(fēng), 染十指rou情,把月光彈破, 碎成了星空, 青春而悄皮...
    天山木蘭閱讀 214評(píng)論 0 0

友情鏈接更多精彩內(nèi)容