1.5虚幻引擎中的反射系统
反射系统通俗易懂就是虚幻引擎中用于处理游戏对象的系统。
该系统用来利用、查询以及操作关于C++类、结构体、函数 、成员变量以及枚举的信息。通过反射,虚幻可以实现序列化,GC(垃圾回收),网络复制,C++蓝图通信等重要功能。
官方文档:虚幻引擎中的反射系统 | 虚幻引擎 5.4 文档 | Epic Developer Community (epicgames.com)
1.5.1反射系统工具概述
虚幻编译工具(UnrealBuldTool)和虚幻头工具(UnrealHeaderTool)这些工具是为了简化多平台编译方便用户配置更改平台的参数和编译选项。
虚幻编译工具(UnrealBuldTool,UBT,C#):该工具处理项目编译工作,逐个将引擎模块编译并逐个处理依赖,而Target.cs、Build.cs都是为为此服务,从而将项目与引擎相关联。
虚幻头工具(UnrealHeaderTool,UHT,C++):支持UObject系统的自定义解析和代码工具,其被HBT调用用来分析转换为标准C++代码
注意: UHT并不是一个真正的C++分析器,它只能理解这个语言的一个子集并且会尝试跳过那些它不需要的文本。只关注那些跟反射类型、函数以及属性。
概括:UBT推动UHT将改装过的虚幻引擎源码转化为标准C++代码,从而UBT编译成二进制文件。
1.5.2反射系统机制
官方文档:虚幻属性系统(反射) - Unreal Engine
在C#中,反射的定义是运行中的程序查看本身的元数据或其它程序的元数据的行为。所谓元数据就是有关程序及其类型(由名称、数据结构、行为及约束条件组成)的数据被称为元数据。
总的来说反射数据描述了类在运行时的内容。这些数据所存储的信息包括类的名称、类中的数据成员、每个数据成员的类型、每个成员位于对象内存映像的偏移(offset),此外,它也包含类的所有成员函数信息。
代码中
为了标记一个头文件包含反射类型,需要在文件顶部添加一个特殊的include文件。该文件必须放在#include的最后,这让UHT知道它需要考虑这个文件,并且在反射系统的实现里也是需要的。
#include "FileName.generated.h"
声明完后,可以使用UENUM()、UCLASS()、USTRUCT()、UFUNCTION()、以及UPROPERTY()来在头文件中注解不同的类型以及成员变量。每一个宏都会出现在类型或者成员变量的前面,并且可以包含额外的修饰符关键字。
示例代码:
#include "StrategyTypes.h"
#include "StrategyChar.generated.h"
UCLASS(Abstract)
class AStrategyChar : public ACharacter, public IStrategyTeamInterface
{
GENERATED_BODY()
/** How many resources this pawn is worth when it dies. */
UPROPERTY(EditAnywhere, Category = Pawn)
int32 ResourcesToGather;
/** set attachment for weapon slot */
UFUNCTION(BlueprintCallable, Category = Attachment)
void SetWeaponAttachment(class UStrategyAttachment* Weapon);
UFUNCTION(BlueprintCallable, Category = Attachment)
bool IsWeaponAttached();
protected:
/** melee anim */
UPROPERTY(EditDefaultsOnly, Category = Pawn)
UAnimMontage* MeleeAnim;
/** Armor attachment slot */
UPROPERTY()
UStrategyAttachment* ArmorSlot;
/** team number */
uint8 MyTeamNum;
[more code omitted]
};
分析此代码可知该类公有继承ACharscter和IStrategyTeamInterface,在内部定义了一个GENERATED_BODY()的宏。GENERATED_BODY()在需要反射的类或结构体里面是必要的,且必须被放置在类体的最前方,它们会被替换成额外的函数和typedef。
概括:UBT推动UHT将改装过的虚幻引擎源码转化为标准C++代码,从而UBT编译成二进制文件。
注意:C++本身不支持反射,虚幻在C++的基础上搭建了自己的一套反射机制。反射系统是选择性加入的,只有主动标记的类型、属性、方法会被反射系统追踪(暴露给反射系统的类型或属性添加注解),UnrealHeaderTool(UHT)会收集这些信息,生成用于支持反射机制的C++代码,然后再编译工程。