Unity序列化文件到底是如何关联MonoBehaviour的

我们知道Unity序列化文件的格式是YAML,在Inspector面板上可以拖拽的脚本、资源会被视为引用。以下YAML语句描述了一条对资源的引用:

{fileID: -1155515603, guid: 7f2f46c0507666e498f75cc4d6f91a07, type: 3}

打包后,GUID是一个32长度的string,Runtime进行处理时速度较慢,因此会被转换为int64的PathID,这一点可以才AssetStudio中解压后证实。

对于资源文件,打包时会建立一张Resource清单,包含了PathID和资源的对于关系,但是对于Mono脚本文件,这个关联机制是怎样的呢?

通过阅读AssetStudio的源码的可以发现,序列化文件引用的MonoBehaviour脚本,在打包时会被转换为序列化的MonoBehaviour类,该类持有一个PPtr,而在MonoScript中则记录了类的信息:

public sealed class MonoScript : NamedObject
{
    public string m_ClassName;
    public string m_Namespace = string.Empty;
    public string m_AssemblyName;
    // ...
}

查看Unity(泄露的)源码可以发现,MonoManager提供了运行时通过这些信息获取对应类的API,并在Mono和IL2CPP下分别实现,因此我们下结论:

  1. 编辑器下,当创建一个MonoBehaviour时,Unity会分析该cs文件中同名的MonoBehaviour类(Unity要求文件名和类名一致,想必是便于分析),并维护一张cs文件GUID + FileID与类信息的关系表,无论该MonoBehaviour是在asmdef的Dll中还是直接在Assets下(在Dll中时,Dll中类的GUID为Dll的GUID,FileID则不同,都是负数)。
  2. 打包时,Unity会将关系表写入MonoScript中进行序列化,最后写入到SerializedFile中,SerializeFile随后被打入Resources或者AssetBundle。SerializeFile是Unity打包序列化YAML的格式。
  3. 运行期间,加载含有MonoBehaviour脚本时,Unity通过MonoScript包含的信息获取类信息,并对MonoBehaviour进行实例化,最后填充该MonoBehaviour实例的自定义的序列化参数,完成加载。

你可能感兴趣的:(Unity,逆向工程,Unity,序列化,MonoBehaviour)