Notifications
Article
最佳实践(一)
Published 8 months ago
115
0
Assets,Objects和序列化
本文翻译自官方最佳实践系列
原文地址为:assets-objects-and-serialization
部分专有名词,技术术语保留原文
部分解释性段落省略,仅翻译技术相关部分
Checked with version: 5.4
Difficulty: Advanced
This is the second chapter in a series of articles covering Assets, Resources and resource management in Unity 5.

This chapter covers the deep internals of Unity's serialization system and how Unity maintains robust references between different Objects, both in the Unity Editor and at runtime. It also discusses the technical distinctions between Objects and Assets. The topics covered here are fundamental to understanding how to efficiently load and unload Assets in Unity. Proper Asset management is crucial to keeping loading times short and memory usage low.
这篇文章覆盖了Unity序列化的内核以及Unity是如何同时在编辑器和运行时维护不同Objects间的鲁棒性。同时本文也将探讨Objects和Assets在技术上的分别。本文的内容是理解如何在Unity中高效的加载和卸载Assets的基础。正确的管理Asset是缩短加载时间和降低内存使用的关键所在。
1.1. Inside Assets and Objects
1.1.深入Assets和Objects
To understand how to properly manage data in Unity, it is important to understand how Unity identifies and serializes data. The first key point is the distinction between Assets and UnityEngine.Objects.
想要理解在Unity中如何正确管理数据的关键,在于理解Unity是如何识别和序列化数据的。第一个关键点,是Assets和UnityEngine.Objects
An Asset is a file on disk, stored in the Assets folder of a Unity project. For example, texture files, material files and FBX files are all Assets. Some Assets contain data in formats native to Unity, such as materials. Other Assets need to be processed into native formats, such as FBX files.
一个Asset就是磁盘上的一个文件,它存储在Unity工程的Assets文件夹中。比如,纹理,材质和FBX文件,都是Assets。 一些Assets采用Unity原始数据格式,比如纹理。其他Assets需要导入成原生数据格式,比如FBX
A UnityEngine.Object, or Object with a capitalized 'O', is a set of serialized data collectively describing a specific instance of a resource. This can be any type of resource which the Unity Engine uses, such as a mesh, a sprite, an AudioClip or an AnimationClip. All Objects are subclasses of the UnityEngine.Object base class.
一个UnityEngine.Object,或者大写字母O开头的Object,是描述某种资源实例的序列化数据的集合。其中资源类型可以使Unity引擎使用的任意类型,比如网格(mesh),精灵(sprite),声音(AudioClip)或者动画(AnimationClip)。所有Objects都是UnityEngine.Object的子类。
While most Object types are built-in, there are two special types.
大部分Object类型都是内建的,只有两个比较特殊。
A ScriptableObject provides a convenient system for developers to define their own data types. These types can be natively serialized and deserialized by Unity, and manipulated in the Unity Editor's Inspector window.
ScriptableObject是为开发者提供了一种方便的自定义类型。Unity原生支持它的序列化和反序列化。它也可以在Unity Editor的Inspector窗口中操作。
A MonoBehaviour provides a wrapper that links to a MonoScript. A MonoScript is an internal data type that Unity uses to hold a reference to a specific scripting class within a specific assembly and namespace. The MonoScript does not contain any actual executable code.
MonoBehaviour提供了与MonoScript的链接的封装。MonoScript是一种内部数据类型,Unity用它来持有对特定程序集和名字空间下,特定脚本类的引用。MonoScript并不包含任何实际执行的代码。
There is a one-to-many relationship between Assets and Objects: that is, any given Asset file contains one or more Objects.
Assets和Objects之间是一对多的关系。也就是说,任何给定的Asset文件中都包含一个或多个Objects
1.2. Inter-Object references
Object内部引用
All UnityEngine.Objects can have references to other UnityEngine.Objects. These other Objects may reside within the same Asset file, or may be imported from other Asset files. For example, a material Object usually has one or more references to texture Objects. These texture Objects are generally imported from one or more texture Asset files (such as PNGs or JPGs).
所有的UnityEngine.Objects都可以引用其他的UnityEngine.Objects. 被引用的这个Object可能存在于同一个Asset文件,也可能从其他Asset文件导入。比如,一个材质Object通常引用一个或多个纹理Objects。而这些纹理Objects一般是从一个或多个纹理Asset文件导入的。(比如PNG或者JPG)
When serialized, these references consist of two separate pieces of data: a File GUID and a Local ID. The File GUID identifies the Asset file where the target resource is stored. A locally unique(1) Local ID identifies each Object within an Asset file because an Asset file may contain multiple Objects.
经过序列化之后,这些引用会由两部分数据组成:文件的GUID和位置ID。文件GUID标示了目标资源所在的Asset文件。位置ID是本地唯一的(1),它标示了Asset文件中的每个Object。之所以使用位置ID,因为一个文件中可能有多个Objects。
File GUIDs are stored in .meta files. These .meta files are generated when Unity first imports an Asset, and are stored in the same directory as the Asset.
文件GUID存储在.meta文件中。所有meta文件是在Unity第一次导入Asset时候生成的,它们存储在和Asset相同的目录下。
The above identification and referencing system can be seen in a text editor: create a fresh Unity project and change its Editor Settings to expose Visible Meta Files and to serialize Assets as text. Create a material and import a texture into the project. Assign the material to a cube in the scene and save the scene.
可以使用文本编辑器来查看上述的标示和引用系统。创建一个全新的Unity工程,修改Editor Setting,将Meta文件设置为可见同时以文本方式序列化。创建一个材质并且导入一个纹理。将材质指定给一个场景中的正方体并保存场景。
Using a text editor, open the .meta file associated with the material. A line labeled "guid" will appear near the top of the file. This line defines the material Asset's File GUID. To find the Local ID, open the material file in a text editor. The material Object's definition will look like this:
用文本编辑器打开材质所对应的meta文件。在文件开始的位置有一行含有“guid“标签。这一行定义了材质 Asset 文件的文件GUID。要寻找位置ID,需要用文本编辑器打开材质文件。材质的Object定义形如:
--- !u!21 &2100000
Material:
serializedVersion: 3
... more data ...
In the above example, the number preceded by an ampersand is the material's Local ID. If this material Object were located inside an Asset identified by the File GUID "abcdefg", then the material Object could be uniquely identified as the combination of the File GUID "abcdefg" and the Local ID "2100000".
在上述例子中,冠有符号的数字就是材质的位置ID。如果材质Object是位于有文件GUID“abcdefg”标识的Asset中,那么材质Object可以使用文件GUID ‘‘abcedfg’’和位置ID“2100000”的组合来唯一标识。
1.3. Why File GUIDs and Local IDs?
1.3.为什么使用文件GUID和位置ID?
Why is Unity's File GUID and Local ID system necessary? The answer is robustness and to provide a flexible, platform-independent workflow.
为什么Unity的文件GUID和位置ID系统是必须的呢?因为可以保持良好鲁棒性,同时可以提供一种平滑的平台无关的工作流。
The File GUID provides an abstraction of a file's specific location. As long as a specific File GUID can be associated with a specific file, that file's location on disk becomes irrelevant. The file can be freely moved without having to update all Objects referring to the file.
文件GUID抽象了文件物理存储地址。由于特定的文件GUID分配给了特定的文件,从而解耦了文件和它在磁盘上的存储位置。文件可以自由自动而无需更新引用此文件的所有Object。
As any given Asset file may contain (or produce via import) multiple UnityEngine.Object resources, a Local ID is required to unambiguously distinguish each distinct Object.
由于任何给定的Asset文件都可能包换(或通过导入产生)多个UnityEngine.Ojbect资源,所以需要通过本地ID来准确区分每个不同的Object。
If the File GUID associated with an Asset file is lost, then references to all Objects in that Asset file will also be lost. This is why it is important that the .meta files must remain stored with the same filenames and in the same folders as their associated Asset files. Note that Unity will regenerate deleted or misplaced .meta files.
如果某个与Asset文件关联的文件GUID丢失,那么所有用到该文件中Object的引用也会丢失。这就是为什么meta文件必须和它所对应的Asset文件,以相同的文件名和相同的路径存储。注意,Unity会重新生成被删除的或者错位的meta文件。
The Unity Editor has a map of specific file paths to known File GUIDs. A map entry is recorded whenever an Asset is loaded or imported. The map entry links the Asset's specific path to the Asset's File GUID. If the Unity Editor is open when a .meta file goes missing and the Asset's path does not change, the Editor can ensure that the Asset retains the same File GUID.
Unity Editor维护了一个文件路径和文件GUID的映射关系。映射关系会在Asset文件被加载或者导入的时候创建,这个映射关系链接器Asset文件的路径和其对应的文件GUID。如果在Unity Editor打开的状态下,meta文件丢失,但Asset文件路径并没有变化,那么Unity Editor可以保证Asset文件仍持有之前的文件GUID。
If the .meta file is lost while the Unity Editor is closed, or the Asset's path changes without the .meta file moving along with the Asset, then all references to Objects within that Asset will be broken.
如果meta文件在Unity Editor关闭的情况下丢失,或者Asset路径发生改变,而meta文件没有随该文件一同移动,那么所有用到该Asset文件内Object的引用都将失效。
1.4. Composite Assets and importers
1.4.复合Asset文件和导入器
As mentioned in the Inside Assets and Objects section, non-native Asset types must be imported into Unity. This is done via an asset importer. While these importers are usually invoked automatically, they are also exposed to scripts via the AssetImporter API, and its subclasses. For example, the TextureImporter API provides access to the settings used when importing individual texture Assets, such as PNGs and JPGs.
如同在Assets and Objects一段所述,非原生的Asset类型必须导入到Unity中才能使用。导入过程是通过Asset导入器实现的。通常情况下,这些导入器会被自动调用。同时,这些导入器也通过AssetImporter API及其子类,暴露出来供脚本调用。比如说,纹理导入器 API(TextureImporter API)提供了在导入独立纹理Asset资源(如PNG,JPG等)时进行设置导入选项的能力。
The result of the import process is one or more UnityEngine.Objects. These are visible in the Unity Editor as multiple sub-assets within the parent Asset, such as multiple sprites nested beneath a texture Asset that has been imported as a sprite atlas. Each of these Objects will share a File GUID as their source data is stored within the same Asset file. They will be distinguished within the imported texture Asset by a Local ID.
导入结束后会产生一个或多个UnityEngine.Object。在Unity Editor中,他们以一个父Asset文件下,多一个子Asset的形式表现。比如将一张sprite atlas纹理导入后,会产生多个sprite。由于他们的原始数据都存储在同一个的Asset 文件中,所有这些sprite Object会共享一个文件GUID。在导入后的纹理Asset数据中,Unity会通过本地ID来区分他们。
The import process converts source Assets into formats suitable for the target platform selected in the Unity Editor. The import process can include a number of heavyweight operations, such as texture compression. It would be extremely inefficient to run the import process every time the Unity Editor was opened.
在导入过程中,Unity会根据所选的目标发布平台,将原始数据转换为合适的格式。导入过程会包含数个类似纹理压缩这样的重度操作,所以每次打开Unity Editor都执行导入操作是一种非常低效的行为。
Instead, the results of Asset importing are cached in the Library folder. Specifically, the results of the import process are stored in a folder named for the first two digits of the Asset's File GUID. This folder is stored inside the Library/metadata/ folder. The individual Objects are serialized into a single binary file that has a name identical to the Asset's File GUID.
为此,Asset文件导入后的数据会缓存在Library文件中。导入后的数据会被存储在一个以Asset文件GUID前两位命名的文件夹中。该文件夹存储在Library/metadata/文件夹中。Object都会被序列化为一个的二进制文件,该文件的文件名和所对应的Asset文件GUID一样。
This is actually true for all Assets, not just non-native Assets. However, native assets do not require lengthy conversion processes or re-serialization.
实际上,不只是非原生的Asset,所有的Asset都会这样处理。然而,原生的Asset不需要冗长的转换过程,也不需要重新序列化。
(待续)↩

GaoChuan
Unity DRM (Great China) - Programmer
2
Comments