Unity文件、文件引用、Meta详解
原文链接:https://blog.uwa4d.com/archives/USparkle_inf_UnityEngine.html
这是侑虎科技第381篇原创文章,感谢作者陈广忠供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群465082844)
作者个人主页:https://codegize.cnblogs.com,同时,作者也是U Sparkle活动参与者哦,UWA欢迎更多开发朋友加入U Sparkle开发者计划,这个舞台有你更精彩!
本文详细讲解了Unity引擎各种类型文件的信息内容、用法和使用场景,帮助研发团队对于引擎文件进行更好的理解和掌握。
一、Unity项目中Assets目录下常见的文件类型
在Unity3d中一般存在这么几种文件:
- 资源文件
- 代码文件
- 序列化文件
- 文本文档
- 非序列化文件
- Meta文件
1、资源文件
资源文件指一些创建好并且不再修改的文件。这样的文件一般是美术设计师和音频视频设计师创造的文件,比如FBX文件、贴图文件、音频文件、视频文件和动画文件(虽然动画文件可以被认为是配置文件,不过在由于一般不会去做修改,所以也认为是资源文件)。像这类文件,Unity中都会在导入时进行转化。每一个类型都对应一个AssetImporter,比如AudioImporter、TextureImporter、ModelImport等等。在Unity中点击这样的资源,在Inspector面板会出现设置界面,如下图所示是一个FBX的设置界面:
2、代码文件
代码文件包括所有的代码文件、代码库文件、Shader文件等。在导入时,Unity会进行一次编译。
3、序列化文件(数据文件)
序列化文件通常是指Unity能够序列化的文件,一般是Unity自身的一些类型,比如Prefab(预制体)、Unity3d(场景)文件、Asset(ScriptableObject)文件、Mat文件(材质球),这些文件能够在运行时直接反序列化为对应类的一个实例。
4、文本文档
文本文档比较特殊,它不是序列化文件,但是Unity可以识别为TextAsset。很像资源文件,但是又不需要资源文件那样进行设置和转化,比如txt、xml文件等等。
5、非序列化文件
非序列文件是Unity无法识别的文件,比如一个文件夹也会被认为是一个文件,但是无法识别。
6、Meta文件
Meta文件在Unity中的作用非常关键,它有2个作用:
定义在它同目录下,同名的非Meta文件的唯一ID:GUID。而对于Unity的序列化文件来说,引用的对象用的就是这个GUID。所以一旦Meta中的GUID变更了,就要注意,它很可能引起一场引用丢失的灾难。
存储资源文件的ImportSetting数据。在上文中资源文件是有ImportSetting数据的,这个数据正数存储在Meta文件中。ImportSetting中专门有存储Assetbundle相关的数据。这些数据帮助编辑器去搜集所有需要打包的文件并分门别类。所以每一次修改配置都会修改meta文件。
二、Meta文件详解——Unity GUID/LocalID系统
由于Meta文件的重要性,这里先说说Meta文件的数据结构。Meta文件实质上是一个文本文档,只是采用的是一种叫做YAML的格式来写的(见Description of the Format)。Unity中的序列化文件都是用这个格式类写的,比如Prefab、场景等(后文会继续)。
我们使用Nodepad++打开一个Meta文件,然后在菜单中将语言设置为YAML,如下图所示:
这是一个Asset文件(ScriptableObject)的meta文件
1、GUID
Guid是Meta中最最最重要的数据。这个Guid代表了这个文件,无论这个文件是什么类型(甚至是文件夹)。换句话说,通过GUID就可以找到工程中的这个文件,无论它在项目的什么位置。在编辑器中使用AssetDatabase.GUIDToAssetPath和AssetDatabase.AssetPathToGUID进行互转。
所以在每次svn提交时如果发现有Meta文件变更,一定要打开看一下。看看这个Guid是否被更改。理论上是不需要更改的。
2、ImportSetting数据
后面比较重要的数据是ImportSetting数据。根据不同的文件类型,它的数据是不同的ImportSetting数据,比如上面的NativeFormatImporter、ModelImporter、AudioImporter等等。只要对照Inspector面板中的条目,都可以看懂每一行的意义。
所以知道这个之后,我们可以发现,假如我们把一个文件和这个文件的Meta文件从一个Unity工程复制到另一个Unity工程中,它的配置是不会变的(以前在2个工程手动裁剪同一个模型的20个动画真是傻到家了,直接将这个Fbx和它的Meta文件拷贝过去就行!)。
3、FileID(LocalID)
有一个问题是,如果是一个图集,下面有若干个图片,那么,这个GUID怎么对应一个文件呢?是的,对于一个文件下有多个文件的情况,就需要另外一个ID来表示,这就是LocalID。更习惯用Meta文件中的名字FileID。FileID存储方式有2种:
对于资源文件,非序列化文件,由于一般不会去更改源文件,所以FileID存储在meta文件中。以下是一个Fbx文件的Meta文件:
对于序列化文件,自身数据里面会存储自身的FileID,也会记录所有子文件的FileID(更多关于序列化文件的数据,见下文)。比如对于这样的AnimatorController。它本身的数据如下,除了本身的FileID为9100000外,记录了4个AnimatorClip的FileID。而meta文件中只有自身的FileID。
回到本节一开始的问题,如果是图集,因为是图片本身是资源文件,所以会有FileID存储在对应的Meta文件中。打开任意一个图集,比如以下这个图集对应的Meta文件:
至此就是整个Unity的GUID/LocalID系统的基础了。通过GUID找到任何一个文件,通过FileID找到其中的某个子文件。
三、序列化文件详解——Unity文件引用系统
上文已经提到,对于所有的序列化文件,Unity采用的是YAML来书写。所以对于一个Unity3d(场景)文件、prefab文件、材质、控制器等都可以用文本文档软件打开。这里还是用Notepad++打开。
为了能够简洁地说明问题,我们在Unity中创建一个新的场景,然后创建2个Cube,一个做成Prefab。如图所示:
保存之后,用Notepad++打开这个1.Unity3d。然后在菜单中设置语言为YAML。
可以看到大概的数据:
- OcclusionCullingSettings裁剪数据(菜单Window->Occlusion面板中的数据)
- RenderSettings(菜单Window->Lighting->Settings面板中的部分数据)
- LightmapSettings(菜单Window->Lighting->Settings面板中的其他部分数据)
- NavMeshSettings(菜单Window->Navigation面板中的数据)
- 之后就是场景中的物件的数据
1、GameObject数据
展开第一个GameObject数据,可以看到这个的Name就是Main Camera(如果你的第一个GameObject数据不是Main Camera也没关系,下面肯定某一个是Main Camera,展开那个数据也是一样的结构)。
这个物体上有4个组件,一一对应下面的数据。这就是物体内的引用关系。每一个Unity对象都会有一个FileID,然后在需要引用时,使用这些FileID即可。所以在实例化一个这样的GameObject时,只要依照次序,依次创建物体,组件,初始化数据并进行引用绑定即可在场景中生成一个实例。
我们在Inspector面板中的右上角点击,然后选择Debug转成Debug模式下的Inspector面板:
在Hierarchy面板中选中Main Camera可以看到如图所示,所有的组件的LocalIdentfierInFile的值就是刚刚在Notepad++中看到的数据:
这里有一点,我们看到有一个叫做InstanceID的数据。这个是Unity中一个实例的ID。每一个Unity实例都会有一个InstanceID。在运行时,可以使用UnityEngine.Object的GetInstanceID获取。但是要注意的是,每一次运行,相当于重新生成了新的实例,所以这个值是可变的。
2、组件数据
在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息息相关)。
3、Prefab数据
在YAML的最下面有一个数据是Prefab数据:
看起来很复杂,但是实际上,它就保存了最重要的几个数据:
- Modification:每个组件的修改数据列表,但凡修改的数据,都会在这里体现。
- ParentPrefab:表示是哪一个Prefab。
所以上面的数据就是GUID为27f1445c35c923741a22e4948c4da980的Prefab,修改后的FileID为4126423848245890的一堆数据和FileID为1854796474342856的Name数据。
通过打开我们制作的Cube的Prefab文件及其meta文件,我们可以看到,Meta文件中的GUID就是那个,而Prefab中存在4126423848245890(Transform)和1854796474342856(GameObject)
OK,至此,序列化文件的数据和引用的原理都已完毕。
文末,再次感谢陈广忠的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)。
也欢迎大家来积极参与U Sparkle开发者计划,简称"US",代表你和我,代表UWA和开发者在一起!
Unity文件、文件引用、Meta详解相关推荐
- python怎么导入文件-Python文件如何引入?详解引入Python文件步骤
python基本语法--引入Python文件 1.新建python文件 :在同目录lib下创建mylib.py和loadlib.py两个文件 2.在mylib.py文件中创建一个Hello的类 并且给 ...
- 【C++】C++中的头文件(.h)—详解(2)
接上... [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 头文件中写些什么 在上篇博客中写到头文件本身不参与编译,但是它们被包含到源文件中 ...
- 【C++】C++中的头文件(.h)—详解(1)
[fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 前言 之前写过一篇<C++中头文件的使用>,那篇文章主要讲述C++中头文件的使用 ...
- python源程序文件的扩展名_python程序文件扩展名知识点详解
python程序文件的扩展名称是什么 python程序的扩展名有.py..pyc..pyo和.pyd..py是源文件,.pyc是源文件编译后的文件,.pyo是源文件优化编译后的文件,.pyd是其他语言 ...
- php解析bt,PHP基于闭包思想实现的BT(torrent)文件解析工具实例详解
PHP基于闭包思想实现的BT(torrent)文件解析工具实例详解 发布于 2017-09-08 20:05:36 | 124 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP( ...
- python打开文件的语法_python27语法Python文件打开方式实例详解【a、a+、r+、w+区别】...
本文实例讲述了Python文件打开方式.分享给大家供大家参考,具体如下: 第一步 排除文件打开方式错误: r只读,r+读写,不创建 w新建只写,w+新建读写,二者都会将文件内容清零 (以w方式打开,不 ...
- Linux 执行文件查找命令 which 详解
某个文件不知道放在哪里了,通常可以使用下面的一些命令来查找: which 查看可执行文件的位置 whereis 查看文件的位置 locate 配合数据库查看文件位置 find 实际搜寻硬盘查 ...
- SVN删除文件及其恢复问题详解
SVN删除文件及其恢复问题详解 转自:http://developer.51cto.com/art/201006/203161.htm 本节我们一起来学习一下SVN删除文件及其恢复问题,和大家分享一下 ...
- hadoop文件存储位置_Hadoop文件的存储格式实例详解
sequence文件存储格式 1.txt 纯文本格式,若干行记录.默认用字符编码存储 2.SequenceFile格式(顺序文件格式,可进行切割) key-value 格式进行存储,最终形成的是一个二 ...
- STM32固件库文件树及构成详解
(想要pfd格式文件的可以留下邮箱) STM32固件库文件树及构成详解(库版本:STM32F10x_StdPeriph_Lib_V3.5.0) 库减压后所有文件夹构成如下: /
最新文章
- Python使用matplotlib绘图并去除颜色样条colorbar实战:remove colorbar from figure in matplotlib
- framebuffer的入门介绍-实现程序分析【转】
- 15 -Flask构建弹幕微电影网站-基于角色的访问控制
- php博客添加live2d,在博客中增加自己的live2d纸片人模型方法
- Android中使用Notification在通知栏中显示通知
- 神策数据上线 IPTV Demo ,三大价值助力数据驱动
- matlab显示像素分布,MATLAb-----7--------如何动态显示鼠标的坐标值和图像像素值
- boost::sort模块spreadsort 完全排序的数据示例
- leetcode -- 515. Find Largest Value in Each Tree Row
- Mysql常用语法总结
- 优化网站设计系列文章总结和导读
- 【AI面试题】AlexNet、VGGNet、GoogLeNet,ResNet等网络之间的区别是什么
- 为什么云原生+分布式是数据库的未来?
- cc2530定时器和捕获比较_STM32学习笔记07—基础定时器实验
- 谷歌硬盘 idm_为什么Google搜索结果比本地硬盘查询要快?
- ClientKey实现登录QQ空间,并设置背景音乐
- 对于网络文学而言 计算机叙事,【网络文学论文】传统文学中网络文学特征研究(共4573字)...
- java web实战宝典李宁,《Java Web编程实战宝典》李宁,刘岩,张国平著【摘要 书评 在线阅读】-苏宁易购图书...
- 仙人掌相关问题的处理方法(未完待续)
- 高德地图实现卫星图-区域掩模3D