YAML 第二章 YAML与Unity

  |   0 评论   |   0 浏览

简介

Unity引擎对资源和对象序列化可以使用二进制进行存储,同时也可以使用YAML格式的文本文件进行序列化,本文中将对Unity使用YAML序列化进行详细的阐述,希望可以更加深入了解Unity的序列化

声明

本文中的内容属于个人总结整理而来,个人水平有限,对于部分细节难免有理解错误及遗漏之处,如果您在阅读过程中有所发现,希望您能指正,同时文章中的部分内容也参考了其它大神的文章,如果文章中的内容侵犯了您的权益,表示非常歉意,请您指出,我将尽快修改。

如果您进行转载,请标明出处。

YAML学习笔记二 YAML与Unity(http://www.liyubin.com/articles/2019/03/14/1552530933869.html)

Unity中资源与对象

  • Unity中资源(Asset)

    Asset是存储在Unity项目的Assets文件夹中的文件,例如常见的Texture,Model及Audio等,某些资源包含了Unity原生格式的数据,如Material,对于其它的Asset需要处理为原生的格式,如将3DMax中的模型生成为FBX格式文件,同时在Unity处理成原生的格式

  • Unity中的对象(Object)

    Object是一组序列化的数据,描述了资源特定实例

  • Unity中特殊Object类型

    大部分的Object类型都是内置的,但是有两种特殊的类型

    • ScriptableObject类型

      ScriptableObject为开发者提供了一个方便序列的方式,可以使开发者定义自己的数据类型,这些类型可以通过Unity进行本地序列化及反序列化,并且可以在Unity的属性面板中进行操作

    • MonoBehaviour类型

      MonoBehaviour提供了一个链接到MonoScript的封装器,MonoScript是Unity用来在特定程序集和命名空间内,保存对特定脚本类的引用的内部数据类型,MonoScript不包含任何实际可执行代码

      PS:C#脚本对于Unity来说也是一种资源,MonoScript继承自TextAsset,可以通过

Unity中对象的引用

所有的UnityEngine.Object对象都可以引用其它的UnityEngine.Object对象,其它的Object可能存在于相同的资源文件中或需要从其它的资源文件导入,比如:一个材质Object通过有一个或多个纹理Object的引用,这些纹理Object一般是从一个或者多个纹理资源文件中导入的

序列化后,这些对象的引用由两部分数据组成:文件的GUID及本地ID,文件的GUID用于识别资源(asset)中的目标资源,而本地ID负责识别单个资源文件中的Object,因为一个资源文件可能会包含多个Object

Unity中GUID与本地ID

  • 文件GUID

    文件的GUID存储于.meta文件中,资源在首次导入时会生成,并且与资源文件存储在同一个目录中,如果项目中未找到.meta文件,是因为项目中未显示meta文件,开启的方法为:Edit->Project Settings->Editor->Version Control将Mode选择修改为Visibale Meta Files,则项目中资源对应会出现.meta文件。

    meta文件中的guid行定义了资源的GUID,如:

fileFormatVersion: 2
guid: 9241db08d41a93f4781ea5b5f0943468
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 本地ID

一般情况下Unity中资源序列化使用二进制的形式存储,可以切换使用YAML格式序列化,设置的方法为:Edit->Project Settings->Editor->Asset Serialization将Mode选择修改为Force Text,则Unity的资源将使用YAML文本存储。

简易的序列化文件内容如:

--- !u!1 &6
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
importerVersion: 3
m_Component:

  • 4: {fileID: 8}
  • 33: {fileID: 12}
  • 65: {fileID: 13}
  • 23: {fileID: 11}
    m_Layer: 0
    m_Name: Cube
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
上述文件中前面有&符号的数字就是本地ID,如"--- !u!1 &7516900628893524171"中的"7516900628893524171"为本地ID

+ 为何要使用GUID与本地ID

为什么Unity需要GUID和本地ID?,答案是为了健壮性,并提供一个灵活,并且与平台无关的工作流程。
文件的GUID提供文件特定位置的抽象表达,只要有与特定文件关联的GUID,那么这个文件在磁盘上的位置就无关紧要了,该文件可以自由移动,而无需更新引用该文件的对象。
由于任何给定的资产文件可能包含(或者通过导入生成的)多个UnityEngine.Object资源,因此,需要本地ID来明确区分每个不同的对象。
如果与资产文件关联的文件GUID丢失,那么对该资产文件中的所有对象的引用也将丢失,这就是为什么.meta文件必须和对应的资产文件保持相同的文件名,并且保存在相同的文件夹中,请注意,Unity会重新生成已删除或者错位的.meta文件。

Unity编辑器具有到已知GUID的文件的映射,无论何时加载或导入资产,都会记录一个映射关系,映射关系将资产的路径链接到资产的GUID,如果Unity编辑器在打开状态下,meta文件丢失,但是资源路径没有更改,编辑器可以确保保留相同的GUID。

如果在Untiy编辑器关闭时丢失了meta文件,或者资产的路径发生变化,而meta文件没有和资产一起移动,那么所有对该资产中对象的引用都会丢失。

# Unity中YAML序列化数据
Unity中的资或对象,以用资源中使用的其它的资源或对象,包括存储的Prefab、Scene等都序列为YAML文档

一个空prefab文档序列化内容:

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &7516900628893524171
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:

  • component: {fileID: 7746837702187571576}
    m_Layer: 0
    m_Name: GameObject
    m_TagString: Untagged
    m_Icon: {fileID: 0}
    m_NavMeshLayer: 0
    m_StaticEditorFlags: 0
    m_IsActive: 1
    --- !u!4 &7746837702187571576
    Transform:
    m_ObjectHideFlags: 0
    m_CorrespondingSourceObject: {fileID: 0}
    m_PrefabInstance: {fileID: 0}
    m_PrefabAsset: {fileID: 0}
    m_GameObject: {fileID: 7516900628893524171}
    m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
    m_LocalPosition: {x: 0, y: 0, z: 0}
    m_LocalScale: {x: 1, y: 1, z: 1}
    m_Children: []
    m_Father: {fileID: 0}
    m_RootOrder: 0
    m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
  • %YAML 1.1

    指定使用的YAML的版本为1.1

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

    使用TAG指令定义

  • --- !u!1 &7516900628893524171

    文本中的"!u!1"中的1表示当前对象类型的映射ID,基中1代表着GameObject类型。Unity为各种类型分配了ID,详细的参见:Unity中YAMLID引用。对于&符号后的"7516900628893524171"表示资源的本地ID

  • m_ObjectHideFlags: 0

    表示对应类型的存储的属性及其值,Unity自身的属性中多以m_开头,如果自定义的类型中的属性名称与之也将对应

  • m_PrefabAsset: {fileID: 0}

    表示引用其它的资源类型,其中0代表着没有引用,如果为非0的值代表对本地ID指向的资源的引用

PS:在Unity开发中,如果关心文档的内容,会发现重新设置引用的资源后,对应的引用资源的本地ID也会发生变化。
TODO:目前尚未找到对应引用与本地ID的对应关系

章节

参考资料


标题:YAML 第二章 YAML与Unity
作者:liyubin
地址:http://www.liyubin.com/articles/2019/03/14/1552530933869.html