text: UnrealEngine 笔记：反射
  Unreal引擎中的反射并不是指图形学意义上的“反射”（例如材质的反射效果等），而是指编程语言中的一种机制。此机制的概念最早由 Smith 在1982年提出，主要是指程序可以访问、检测和修改它本身状态或行为的一种能力，即在运行过程中检查自己的类，函数，成员变量，结构体等等。通俗的讲就是我们希望在程序运行时获取一个类，知道这个类有哪些成员变量、成员函数，以及获取这些成员变量和函数的名字，而这需要我们在程序运行前完成类似于“类有哪些成员变量、成员函数”这样的信息的注册。这样的机制在 C#、Java 中已经存在，C++ 中虽然引入了 typeid 运算符，可以在运行时获取类型相关信息，但是保存的信息仍无法支撑反射的机制。Unreal引擎在符合 C++ 标准的基础上增加其自己的反射实现来支持引擎的动态功能，如垃圾回收、序列化、网络复制和蓝图/C++通信等。这些动态功能是可选的，意味着使用时必须将正确的标记添加到类型，否则虚幻将忽略它们，而且不会为它们生成反射数据。另外，在 Unreal 项目开发中主流的一些脚本语言就是基于虚幻的反射机制形成的。Unreal引擎是利用 UHT（Unreal Header Tool）配合实现了反射机制。在讲解 UHT 具体如何工作之前，我们需要思考一个问题，在开发中经常会发现很多头文件中都包含有 include “xxx.generated.h”，也经常会用到 UCLASS()、UPROPERTY()、UFUNCTION()宏，已知在宏中填充元数据说明符可以控制其与引擎和编辑器各方面的相处方式（如蓝图/C++通信等），那么为什么引擎中会有这些东西呢？我们分析后不难发现，Unreal引擎中的一个 UClass，其实可以理解为包含 UProperty 和 UFunction 的一个数据结构： 随后虚幻引擎做的事情其实是，把C++类（也就是真正的“成员变量”和“成员函数”）与 UClass 中的对应的“Property 数据类型”和“Function 数据类型”绑定起来。 如果一个C++类的头文件中包含有 include “xxx.generated.h”，这就意味着该头文件加入了UE的反射系统。当我们编写完代码进行编译时， UBT（Unreal Build Tool）开始扫描所有的头文件，记录下包含有反射类型的模块，然后调用 UHT。UHT 解析记录模块的头文件，扫描文件中的标记，生成用于支持反射的C++代码，反射代码包括xxx.generated.h 和 xxx.generated.cpp。[2]UHT 扫描标记生成代码的过程是用来记录一种方法，一种如何获取信息或者说是去哪里（标记处）获取信息的方法。当然仅仅记录获取信息的过程还不足够，还需要在加载的时候调用记录好的过程来进行实际的记录。实质上来说，加载信息是利用了一个简单的C++机制：静态全局变量的初始化先于 main 函数执行。在生成好的 xxx.generated.cpp 文件中，我们会看到一个 IMPLEMENT_CLASS 宏，这个宏展开后实质上完成了两个内容： 总的来讲就是在 main 函数执行前，先执行 UClassCompiledInDefer 函数。这样虚幻引擎就知道有哪个类是需要延迟加载的。借助这个技巧，虚幻引擎能够在启动前就给全部的类发个号，等时机成熟再一个一个加载信息。以下列出了一些基本的标记：定义下面需要用到的枚举和类创建对象类并获取UClass实例