天天看點

淺談有關于Unity3D序列化及資源管理       

首先要明确的問題

Unity自帶的Serializable特性無法對GameObject進行初始化,幾乎沒有任何意義

EsaySave插件可以對遊戲内的資料包括Gameobject進行序列化,但是實際使用情況沒有經過測試

GUID

Unity引擎本身生成的GUID本身不儲存任何資料,隻是作為一個索引,實際資料存在Library/matedata檔案夾裡,用GUID頭兩位劃分檔案夾,以GUID作為檔案名,字尾名為info,将檔案路徑等屬性存在info檔案裡,其中,GUID隻作為映射對應檔案所需要的索引

info檔案對中文采用Unicode編碼

生成的GUID是緩存在記憶體中的,如果檔案被删除,GUID及對應的meta檔案及info檔案會被删除,但是如果之後又複原了,那麼Unity會重新生成一份一模一樣的GUID及Mate檔案info檔案,前提是檔案本身沒發生變化,如果删除了檔案又關閉了Unity,那麼下次打開Unity的時候再導入同一個檔案,就會重新生成一個新的GUID及對應的檔案

MateData檔案夾的排序順序:0>字母>1~9

GUID及LocalID(FileID)的建立和使用依賴AssetDataBase類,依賴于Unity3D Editor.dll,是以這一切無法在運作時使用

綜上所述,如果我們想在遊戲運作時進行序列化儲存工作,将無法使用Unity序列化及資源管理的任何特性!但是我們可以從Unity的設計思路中擷取到一些我們需要的,可行的保持依賴的方法

之是以需要一個額外的GUID和FileID來映射對應的檔案夾,是為了保證資源放在Assets檔案夾下的任何位置都可以被索引到

FileID(LocalID)

確定在同一個資源檔案(模型,圖集等)下,所有的對象都有唯一的ID

32位int類型

生成規則:檔案的MD4編碼的前四位byte+字元串"s\0\0\0"+類的命名空間+類名

UnityPrefab

prefab檔案并不存儲具體資源,而是使用了yaml語言描述了一個被序列化的GameObject對象中包含的所有GameObject,Component的資訊。包括互相之間的關系、存儲的資料和引用資訊。

就像這樣:

%YAML 1.1

%TAG !u! tag:unity3d.com,2011:

--- !u!1 &6661200084521074333

GameObject:

m_ObjectHideFlags: 0

m_CorrespondingSourceObject: {fileID: 0}

m_PrefabInstance: {fileID: 0}

m_PrefabAsset: {fileID: 0}

serializedVersion: 6

m_Component:

- component: {fileID: 6661200084521074330}

- component: {fileID: 6661200084521074329}

- component: {fileID: 6661200084521074328}

- component: {fileID: 6661200084521074331}

m_Layer: 9

m_Name: Sphere

m_TagString: Untagged

m_Icon: {fileID: 0}

m_NavMeshLayer: 0

m_StaticEditorFlags: 0

m_IsActive: 1

--- !u!4 &6661200084521074330

Transform:

m_ObjectHideFlags: 0

m_CorrespondingSourceObject: {fileID: 0}

m_PrefabInstance: {fileID: 0}

m_PrefabAsset: {fileID: 0}

m_GameObject: {fileID: 6661200084521074333}

m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}

m_LocalPosition: {x: 1.496, y: 0, z: 0}

m_LocalScale: {x: 1, y: 1, z: 1}

m_Children: []

m_Father: {fileID: 6661200085399109717}

m_RootOrder: 0

m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
           

其中最關鍵的一行

--- !u!1 &6661200084521074333
           

!u! 1描述了這是種什麼元件,詳細的可以在這裡看到

&6661200084521074333
           

這裡描述了這個Component的FileID,在Unity裡,任何物體都有Gameobject及Transform兩個Component,每個Component都會有一個在目前資源檔案中唯一的FileID

m_Component:

- component: {fileID: 6661200084521074330}

- component: {fileID: 6661200084521074329}

- component: {fileID: 6661200084521074328}

- component: {fileID: 6661200084521074331}
           

代表了這個GameObject上有多少個Component,隻包含了目前預制體的目前物體所有的Component,如果一個預制體下有多個GameObject,會分别記錄在不同的GameObjectComponent上

m_Father: {fileID: 6661200085399109717}
           

Transform的父物體的FileID

UnityScene

Scene的序列化和Prefab沒有太多差距,主要是将一些場景的設定當作Component(或者本身就是Component)存了起來,如下:

%YAML 1.1

%TAG !u! tag:unity3d.com,2011:

--- !u!29 &1

OcclusionCullingSettings:

m_ObjectHideFlags: 0

serializedVersion: 2

m_OcclusionBakeSettings:

smallestOccluder: 5

smallestHole: 0.25

backfaceThreshold: 100

m_SceneGUID: 00000000000000000000000000000000

m_OcclusionCullingData: {fileID: 0}

--- !u!104 &2

RenderSettings:

m_ObjectHideFlags: 0

serializedVersion: 9

m_Fog: 0

m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}

m_FogMode: 3

m_FogDensity: 0.01

m_LinearFogStart: 0

m_LinearFogEnd: 300

m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}

m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}

m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}

m_AmbientIntensity: 1

m_AmbientMode: 0

m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}

m_SkyboxMaterial: {fileID: 2100000, guid: c8e304140c860744783e1aa250535791, type: 2}

m_HaloStrength: 0.5

m_FlareStrength: 1

m_FlareFadeSpeed: 3

m_HaloTexture: {fileID: 0}

m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}

m_DefaultReflectionMode: 0

m_DefaultReflectionResolution: 128

m_ReflectionBounces: 1

m_ReflectionIntensity: 1

m_CustomReflection: {fileID: 0}

m_Sun: {fileID: 170076734}

m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}

m_UseRadianceAmbientProbe: 0
           

綜上所述

Unity的資源管理本質是描述檔案和索引檔案的管理,資源檔案具有一個.mate類型的索引檔案,其中有AssetbundleName及GUID等

再通過GUID去找描述檔案,描述檔案裡面有該檔案的路徑,設定等

而Prefab和Scene就是把物體序列化了,并通過GUID和FileID查找

這樣就可以保證無論一個資源檔案在Assets檔案夾下怎麼改動都不會丢失引用

參考資料

https://learn.unity.com/tutorial/assets-resources-and-assetbundles?_ga=2.235901506.299668314.1591067528-1234168545.1589858985#5c7f8528edbc2a002053b5a6

https://abaojin.github.io/2017/02/08/unity-project/

https://forum.unity.com/threads/how-to-get-filename-from-the-local-file-id.693103/

https://www.cnblogs.com/blueberryzzz/p/9097391.html

https://forum.unity.com/threads/yaml-fileid-hash-function-for-dll-scripts.252075/

https://blog.csdn.net/UWA4D/article/details/79847865

繼續閱讀