UE4反射機制學習

參考資料:https://blog.csdn.net/mohuak/article/details/81913532?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase


UE4中反射用於什麼情況?

#define UPROPERTY(...)
#define UFUNCTION(...)
#define USTRUCT(...)
#define UMETA(...)
#define UPARAM(...)
#define UENUM(...)
#define UDELEGATE(...)

// This pair of macros is used to help implement GENERATED_BODY() and GENERATED_USTRUCT_BODY()
#define BODY_MACRO_COMBINE_INNER(A,B,C,D) A##B##C##D
#define BODY_MACRO_COMBINE(A,B,C,D) BODY_MACRO_COMBINE_INNER(A,B,C,D)

// Include a redundant semicolon at the end of the generated code block, so that intellisense parsers can start parsing
// a new declaration if the line number/generated code is out of date.
#define GENERATED_BODY_LEGACY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY_LEGACY);
#define GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY);

當我們給變量/函數/類/結構體添加U###的時候,UHT就會幫助我們實現反射機制

C++與藍圖交互,UE4的變量回收系統,幾乎UE4所有的Module都利用了反射機制


UBT和UHT介紹

UnrealBuildTool(UBT):UE4來編譯各個模塊之間的依賴

UnrealHeaderTool(UHT,C++編譯器強化版):UE4 C++代碼編譯。UHT利用.generated.h信息生成C++反射代碼。完成後,再調用普通的C++編譯器

啓動UE4編譯時,UE4首先調用UHT,檢索.h中的UCLASS、GENERATED_BODY、UPROPERTY、UFUNTION等關鍵字,然後生成generate.h和generate.cpp文件


生成階段

helloworld.generated.h文件中

GENERATED_BODY

#define GENERATED_BODY_LEGACY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY_LEGACY);

對於某個類的GENERATED_BODY來說,CURRENT_FILE_ID定義在該文件的.generated.h文件中

DECLARE_FUNCTION

  1. NavtiveFuncTest定義BlueprintNativeEvent,藍圖和C++均可以實現。在C++中實現的方法要加上NavtiveFuncTest_Implementation(),因爲UBT內部已經實現這部分的定義?(理由見下)
  2. DECLARE_FUNCTION(execNavtiveFuncTest)。聲明一個函數爲execNavtiveFuncTest,會優先調用藍圖方法,如果不存在的話再調用C++的NavtiveFuncTest_Implementation()

DECLARE_CLASS

private: \
	static void StaticRegisterNativesAHelloGameMode(); \
	friend struct Z_Construct_UClass_AHelloGameMode_Statics; \
public: \
	DECLARE_CLASS(AHelloGameMode, AGameModeBase, COMPILED_IN_FLAGS(0 | CLASS_Transient), CASTCLASS_None, TEXT("/Script/helloworld"), NO_API) \
	DECLARE_SERIALIZER(AHelloGameMode)

Generated.cpp文件中

ProcessEvent

static FName NAME_AHelloGameMode_NavtiveFuncTest = FName(TEXT("NavtiveFuncTest"));
void AHelloGameMode::NavtiveFuncTest()
{
	ProcessEvent(FindFunctionChecked(NAME_AHelloGameMode_NavtiveFuncTest),NULL);
}

很明顯,在.cpp文件中,NativeFuncTest函數已經被自動生成。因此對於都可用&&藍圖>C++優先級的情況下,需要加上_Implementablement來聲明,否則會報錯已經定義

IMPLEMENT_CLASS

MPLEMENT_CLASS(AHelloGameMode, 3705664059);
template<> HELLOWORLD_API UClass* StaticClass<AHelloGameMode>()
{
	return AHelloGameMode::StaticClass();
}

收集階段(利用Static自動註冊方式,將UCLASS登記,放進Array統一管理)

在收集階段(上一階段)在IMPLEMENT_CLASS和ConstructClass兩個函數中靜態聲明瞭兩個變量

#define IMPLEMENT_CLASS(TClass, TClassCrc) \
	static TClassCompiledInDefer<TClass> AutoInitialize##TClass(TEXT(#TClass), sizeof(TClass), TClassCrc); \

static FCompiledInDefer Z_CompiledInDefer_UClass_##TClass(Z_Construct_UClass_##TClass, &TClass::StaticClass, TEXT(TPackage), TEXT(#TClass), false);
  • TClassCompiledInDefer(調用UClassCompiledInDefer收集數據)是分配空間
  • FCompiledInDefer(調用UObjectCompiledInDefer收集數據),調用初始化函數
  • 並且將註冊信息放入ClassInfo延遲註冊,如果類太多,全部都要註冊會很卡

void ProcessNewlyLoadedUObjects(FName Package, bool bCanProcessNewlyLoadedObjects)
{
	UClassRegisterAllCompiledInClasses();

	const TArray<UClass* (*)()>& DeferredCompiledInRegistration = GetDeferredCompiledInRegistration();
	const TArray<FPendingStructRegistrant>& DeferredCompiledInStructRegistration = GetDeferredCompiledInStructRegistration();
	const TArray<FPendingEnumRegistrant>& DeferredCompiledInEnumRegistration = GetDeferredCompiledInEnumRegistration();

	bool bNewUObjects = false;
	while (GFirstPendingRegistrant || DeferredCompiledInRegistration.Num() || DeferredCompiledInStructRegistration.Num() || DeferredCompiledInEnumRegistration.Num())
	{
		bNewUObjects = true;
		UObjectProcessRegistrants();
		UObjectLoadAllCompiledInStructs();
		UObjectLoadAllCompiledInDefaultProperties();
	}
}

ProcessNewlyLoadedUObjects用於註冊類,結構體,枚舉的反射信息

收集階段

通過UClassCompiledInDefer收集

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章