UHT(Unreal Header Tool) 是虚幻引擎(Unreal Engine)中的一个重要工具,它用于处理和生成引擎所需的元数据,使得虚幻引擎能够执行许多复杂的功能,如反射、序列化、蓝图交互、垃圾回收等。简而言之,UHT 是虚幻引擎中的“幕后工具”,负责从 C++ 头文件中提取信息,并生成用于引擎运行时的额外代码和元数据。
UHT的作用与工作原理
在虚幻引擎中,C++类、结构体和方法等通常会使用特定的宏标记(如 UCLASS
、UPROPERTY
、UFUNCTION
)来提供额外的信息,这些信息用于引擎的各种系统。UHT 的任务就是读取这些头文件,识别宏,并生成相应的反射信息和元数据。
UHT 实际上是一个构建工具,它在编译阶段工作,处理头文件,分析 C++ 类和方法的声明,并根据标记生成一组“反射”数据。这些数据将在引擎运行时被使用,支持如蓝图、垃圾回收、序列化等功能。
虚幻引擎UHT与Visual Studio的编译配合是一个非常精细的过程,我将详细为你解析:
1.编译流程概述
- UHT作为预编译工具优先运行
- Visual Studio负责最终的代码编译
- 两者协同完成项目构建
2.编译前UHT处理步骤
- 扫描项目源代码
- 识别特殊宏(UCLASS/UPROPERTY等)
- 自动生成额外的中间代码文件
- 生成.generated.h头文件
3.代码生成细节
- 1)为每个标记的类生成反射信息
-
每个
UCLASS()
标记的类都需要生成一个UClass
对象,描述该类的元信息。这个UClass
对象用于虚幻引擎的反射系统,它包含了类的基本信息,如类名、父类、方法和属性等。在 UHT 生成的代码中,
UClass
对象是一个指向类描述的指针,它会通过静态构造函数来进行初始化。这些对象对于引擎动态加载和访问类、对象实例以及蓝图交互至关重要。例如,对于以下的类定义:
UCLASS() class AMyActor : public AActor {UPROPERTY()float Health; };
UHT 会生成一个静态方法来返回该类的
UClass
对象描述:static UClass* GetPrivateStaticClass() {static UClass* Class = nullptr;if (!Class) {// 构建类信息Class = GetPrivateStaticClassBody(StaticPackage(),TEXT("AMyActor"), AActor::StaticClass());}return Class; }
这个静态方法返回了一个指向
AMyActor
类的UClass
对象,该对象包含了类的元数据(如类名、继承关系、构造函数等)。 - 2)创建静态注册函数
- UHT 还会为每个
UCLASS
类生成该类的属性布局信息。这是一个数据结构,描述了类中每个属性的类型、偏移量、名称等信息。 - 3)处理蓝图可调用函数
- UHT 还会为每个
UCLASS
类生成一个包含属性和函数的元数据表,这些表用于存储属性、函数等的额外信息(例如是否可编辑、是否可蓝图调用等)。 -
属性元数据表
对于类中的每个属性(如
UPROPERTY
宏标记的属性),UHT 会生成一个元数据表,描述该属性的类型、名称以及它的其他特性。比如是否允许蓝图编辑、是否可以序列化等。函数元数据表
类似于属性,UHT 还会为类中的每个方法(如
UFUNCTION
宏标记的方法)生成一个元数据表,描述该方法的可调用性、蓝图可见性等特性。 - 4)静态注册函数生成
- 每个
UCLASS
类除了反射信息之外,UHT 还会为类生成一个静态注册函数,用于将类注册到虚幻引擎的类型系统中。这个函数通常会在引擎初始化时被调用,以确保类的反射信息和其他元数据能够被引擎正确加载。
4.Visual Studio编译阶段
- 加载UHT生成的中间文件
- 编译完整的项目源代码
- 链接反射和引擎相关代码
5.配合机制
TEXT
UHT预处理 → 生成中间文件 → VS编译 → 最终二进制
6.关键优化
- 增量编译
- 缓存生成的代码
- 减少重复处理
- 增量编译:只编译修改过的部分,避免全项目重编译,显著减少了编译时间。
- 缓存生成的代码:缓存已经生成的中间代码(如反射信息、属性布局等),避免重复生成,提高编译速度。
- 减少重复处理:通过依赖关系管理、内存缓存等技术,减少了重复的文件扫描、数据解析和不必要的处理步骤。
这就是UHT和Visual Studio协同工作的基本机制。