浅谈有关于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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity3D中的预设物是一个非常有用的功能,它允许我们在不同场景中复用对象和组件,以提高游戏开发效率。预设物的序列化保存和反序列化展示如下: 1. 预设物的序列化保存 当我们创建一个预设物并对其进行修改后,Unity3D会自动将该预设物序列化并保存到硬盘上。序列化是指将对象转换为二进制流的过程,这样我们就可以在硬盘上保存这个对象,以便在需要时重新加载。 2. 预设物的反序列化展示 当我们需要在场景中使用某个预设物时,可以从硬盘上加载并反序列化该预设物。反序列化是指将二进制流转换回对象的过程,这样我们就可以在场景中展示该预设物。 在Unity3D中,可以通过代码来实现预设物的序列化和反序列化操作。例如,下面的代码演示了如何将一个预设物保存到硬盘上: ```csharp public class SavePrefab : MonoBehaviour { public GameObject prefab; public void Save() { string path = "Assets/Prefabs/" + prefab.name + ".prefab"; PrefabUtility.SaveAsPrefabAsset(prefab, path); } } ``` 上述代码中,我们定义了一个SavePrefab类,并在其中定义了一个公共GameObject变量prefab。当我们点击Save按钮时,调用Save方法将该预设物保存到硬盘上。具体实现是通过调用Unity3D内置的PrefabUtility.SaveAsPrefabAsset方法实现的。 此外,在Unity3D中还有一些第三方插件可以帮助我们更方便地进行预设物的序列化和反序列化操作,例如Odin Inspector、Json.NET等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值