Tag:Unity文件,Unity文件引用,Meta文件,GUID,FileID,LocalIDhtml
本文介紹unity工程中的文件類型,文件引用原理和meta文件的yaml結構等node
參考文檔:數據結構
在unity3d中通常存在這麼幾種文件編輯器
資源文件指一些建立好的,而且再也不修改的文件。這樣的文件通常是美術設計師,音頻視頻設計師創造的文件,好比FBX文件,貼圖文件,音頻文件,視頻文件,動畫文件(雖然動畫文件能夠被認爲是配置文件,不過在因爲通常不會去作修改,因此也認爲是資源文件)。像這類文件,unity中都會在導入時進行轉化。每個類型都對應一個AssetImporter,好比AudioImporter,TextureImporter,ModelImport等等。在unity中點擊這樣的資源,在Inspector面板會出現設置界面,以下圖所示是一個FBX的設置界面:svn
代碼文件包括全部的代碼文件,代碼庫文件,shader文件等,在導入時,unity會進行一次編譯。動畫
序列化文件一般是指unity可以序列化的文件,通常是unity自身的一些類型。好比prefab(預製體),unity3d(場景)文件,asset(ScriptableObject)文件.mat文件(材質球),這些文件可以在運行時直接反序列化爲對應類的一個實例。ui
文本文檔比較特殊,它不是序列化文件,可是unity能夠識別爲TextAsset。很像資源文件,可是又不須要資源文件那樣進行設置和轉化。好比txt、xml文件等等。設計
非序列文件是Unity沒法識別的文件,好比一個文件夾也會被認爲是一個文件,可是沒法識別。3d
meta文件在unity中的做用很是關鍵,它有2個做用orm
因爲meta文件的重要性,這裏先說說meta文件的數據結構。meta文件實質上是一個文本文檔,只是採用的是一種叫作YAML的格式來寫的(見Description of the Format)。unity中的序列化文件都是用這個格式類寫的,好比prefab,場景等(後文會繼續)。
咱們使用nodepad++打開一個meta文件,而後在菜單中將語言設置爲YAML,以下圖所示:
這是一個asset文件(ScriptableObject)的meta文件
guid是meta中最最最重要的數據。這個guid表明了這個文件,不管這個文件是什麼類型(甚至是文件夾)。換句話說,經過GUID就能夠找到工程中的這個文件,不管它在項目的什麼位置。在編輯器中使用AssetDatabase.GUIDToAssetPath和AssetDatabase.AssetPathToGUID進行互轉。
因此在每次svn提交時若是發現有meta文件變動,必定要打開看一下。看看這個guid是否被更改。理論上是不須要更改的。
後面比較重要的數據是ImportSetting數據。根據不一樣的文件類型,它的數據是不一樣的ImportSetting數據,好比上面的NativeFormatImporter,ModelImporter,AudioImporter等等。只要對照Inspector面板中的條目,均可以看懂每一行的意義。
因此知道這個以後,咱們能夠發現,假如咱們把一個文件和這個文件的meta文件從一個Unity工程複製到另外一個Unity工程中,它的配置是不會變的。(之前在2個工程手動裁剪同一個模型的20個動畫真是傻到家了,直接將這個fbx和它的meta文件拷貝過去就行!)
有一個問題是,若是是一個圖集,下面有若干個圖片,那麼,這個GUID怎麼對應一個文件呢?是的,對於一個文件下有多個文件的狀況,就須要另一個ID來表示,這就是LocalID。更習慣用meta文件中的名字FileID。
FileID存儲方式有2種
回到本節一開始的問題,若是是圖集,由於是圖片自己是資源文件,因此會有FileID存儲在對應的meta文件中。打開任意一個圖集,好比如下這個圖集對應的meta文件
至此就是整個Unity的GUID/LocalID系統的基礎了。經過GUID找到任何一個文件,經過FileID找到其中的某個子文件。
上文已經提到,對於全部的序列化文件,unity採用的是YAML來書寫。因此對於一個unity3d(場景)文件,prefab文件,材質,控制器等,均可以用文本文檔軟件打開。這裏仍是用Notepad++打開。
爲了可以簡潔地說明問題,咱們在unity中建立一個新的場景,而後建立2個Cube,一個作成Prefab。如圖所示:
保存以後,用Notepad++打開這個1.unity3d。而後在菜單中設置語言爲YAML。
能夠看到大概的數據
展開第一個GameObject,能夠看到這個的Name就是Main Camera。這個物體上有4個組件,一一對應下面的數據。這就是物體內的引用關係。每個Unity對象都會有一個FileID,而後在須要引用時,使用這些FileID便可。因此在實例化一個這樣的GameObject時,只要依照次序,依次建立物體,組件,初始化數據並進行引用綁定便可在場景中生成一個實例。
咱們在Inspector面板中的右上角點擊,而後選擇Debug轉成Debug模式下的Inspector面板
在Hierarchy面板中選中Main Camera能夠看到如圖所示,全部的組件的LocalIdentfierInFile的值就是剛剛在Notepad++中看到的數據
這裏有一點,咱們看到有一個叫作InstanceID的數據。這個是unity中一個實例的ID。每個Unity實例都會有一個InstanceID。在運行時,可使用UnityEngine.Object的GetInstanceID獲取。可是要注意的是,每一次運行,至關於從新生成了新的實例,因此這個值是可變的。(更多細節參考《Unity編輯器下和運行時的加載過程》)
在GameObject以後就是這個GameObject的組件數據(不知道次序會不會亂,理論上不影響)。每個組件的數據基本上就是這個組件的一堆參數了。能夠結合Unity中這個組件的面板來了解每個數據的意義。
這裏有一個問題,好比這裏有一個組件是FlareLayer,可是在YAML裏面只是一個Behaviour(全部Behaviour組件都看不到類型名字),怎麼樣才能知道他是一個FlareLayer?
能夠看到在這個數據上方,在FileID左邊咱們看到一個124。對,這個就是FlareLayer。請參考YAML Class ID Reference,每個unity類型都有一個對應的數字。
那麼自定義腳本類呢?
咱們建立一個Test腳本,繼承MonoBehaviour。裏面什麼都不寫。添加到Main Camera物體上。保存場景而後回到Notepad++。
能夠看到多了一個MonoBehaviour,而且這個裏面有一個m_Script數據,指向對應的GUID及其FileID。上文咱們已經說了,任何一個文件均可以經過GUID找到,而後經過FileID找到它內部的子文件。因此這樣就能識別出這個具體是什麼類了。
咱們往Test中寫2個字段
public int A;
public Test RefTest;
在Main Camera中,設置Test腳本的A值爲111,RefTest設置爲自身。保存後回到Notepad++;
看到數據想必都明白了。
能夠往Test中寫一些其餘類型的數據,看看這些序列化數據放在YAML的哪一個位置!這裏再也不展開(這些數據和編輯器的SerializedProperty息息相關)
在YAML的最下面有一個數據是Prefab數據
看起來很複雜,可是實際上,它就保存了最重要的幾個數據
因此上面的數據就是GUID爲161b04a3180d83a4080b19801daaf356的Prefab,修改後的FileID爲4040867914032966的一堆數據和FileID爲1205630099335284的Name數據。
經過打開咱們製做的Cube的Prefab文件及其meta文件,咱們能夠看到,meta文件中的GUID就是那個,而Prefab中存在4040867914032966(Transform)和1205630099335284(GameObject)
OK,至此,序列化文件的數據和引用的原理都已完畢
我的博客請訪問:http://www.cnblogs.com/CodeGize/