UE4反射编程

获取类名称和类标记

//通过反射获得类名和属性变量
	UStudent* Student = NewObject<UStudent>();
	UClass* StudentClass = Student->GetClass();
	
	//获取类名称
	FString ClassName = StudentClass->GetName();
	UE_LOG(LogTemp, Warning, TEXT("Student's classname is %s, Student's superclassname is %s"), *ClassName, *StudentClass->GetSuperClass()->GetName());

	//获取类标记
	EClassFlags ClassFlags = StudentClass->ClassFlags;
	UE_LOG(LogTemp, Warning, TEXT("Student's classFlag is %x"), ClassFlags);

获得类的属性

//获得类属性,其中是一个链表存储的
for(FProperty* Property  = StudentClass->PropertyLink; Property; Property = Property->PropertyLinkNext)
{
   //类属性的名字
   FString PropertyName = Property->GetName();
   //类属性的类型
   FString PropertyType = Property->GetCPPType();
   if(PropertyType == "FString")
   {
      FStrProperty* StringProperty = CastField<FStrProperty>(Property);
      void* Addr = StringProperty->ContainerPtrToValuePtr<void>(Student);//这里是获得具体类的对象,才能获得属性的值
      FString PropertyValue = StringProperty->GetPropertyValue(Addr);
      //获取属性元数据
      FString CategoryName = StringProperty->GetMetaData(TEXT("Category"));

      UE_LOG(LogTemp, Warning, TEXT("Student's properties has %s, Type is %s, Value is %s, Meta has %s"), *PropertyName, *PropertyType, *PropertyValue, *CategoryName);

      //获得类属性变量后,动态修改属性值
      StringProperty->SetPropertyValue(Addr, "SettingValue");
      FString PropertyValueAfterSetting = StringProperty->GetPropertyValue(Addr);
      UE_LOG(LogTemp, Warning, TEXT("Student's properties has %s, Type is %s, Value is %s"), *PropertyName, *PropertyType, *PropertyValueAfterSetting);

   }
}

获得类的方法

//通过反射获得类的函数
for(TFieldIterator<UFunction> IteratorOfFunction(StudentClass); IteratorOfFunction; ++IteratorOfFunction)
{
   //获取方法名称
   UFunction* Function = *IteratorOfFunction;
   FString FunctionName = Function->GetName();
   UE_LOG(LogTemp, Warning, TEXT("Student's function is %s"), *FunctionName);

   //获取方法标记
   EFunctionFlags FunctionFlags =  Function->FunctionFlags;
   UE_LOG(LogTemp, Warning, TEXT("Student's functionFlag is %x"), FunctionFlags);
   
   //获得函数的参数以及标志位flag
   for(TFieldIterator<FProperty> IteratorOfParam(Function); IteratorOfParam; ++IteratorOfParam)
   {
      FProperty* Param = *IteratorOfParam;
      FString ParamName = Param->GetName();
      FString ParamType = Param->GetCPPType();
      EPropertyFlags ParamFlags =  Param->GetPropertyFlags();
      
      UE_LOG(LogTemp, Warning,
         TEXT("Student's function has %s, ParamType is %s, ParamName is %s, ParamFlag is %x"), *FunctionName, *ParamType, *ParamName, ParamFlags);
   }
}

获取类的父类

//通过子类获得父类   ->GetSuperClass()
UMiddleStudent* MiddleStudent = NewObject<UMiddleStudent>();
UClass* ParentClass = MiddleStudent->GetClass()->GetSuperClass();
FString ParentName = ParentClass->GetName();
UE_LOG(LogTemp, Warning, TEXT("MiddleStudent's Superclassname is %s"), *ParentName);

判断类的从属关系

//判断类的从属关系   Class1->IsChildOf(Class2)
UClass* Class1 = UMiddleStudent::StaticClass();
UClass* Class2 = UStudent::StaticClass();
UClass* Class3 = AActor::StaticClass();

if(Class1->IsChildOf(Class2))
{
   UE_LOG(LogTemp, Warning, TEXT("Class1 is Class2's child"));
}else
{
   UE_LOG(LogTemp, Warning, TEXT("Class1 is not Class2's child"));
}

if(Class3->IsChildOf(Class2))
{
   UE_LOG(LogTemp, Warning, TEXT("Class3 is Class2's child"));
}else
{
   UE_LOG(LogTemp, Warning, TEXT("Class1 is not Class2's child"));
}

查找类继承的子类

//查找特定类的子类   GetDerivedClasses
TArray<UClass*> ClassResults;
GetDerivedClasses(UStudent::StaticClass(), ClassResults, false);
//UE_LOG(LogTemp, Warning, TEXT("Object's child Count has %d"), ClassResults.Num());
for(int32 Index = 0; Index < ClassResults.Num(); ++Index)
{
   UClass* ClassResult = ClassResults[Index];
   FString ClassResultName = ClassResult->GetName();
   UE_LOG(LogTemp, Warning, TEXT("UStudent::StaticClass's child has %s"), *ClassResultName);
}

查找类生成的对象

UGoodMiddleStudent* GMS = NewObject<UGoodMiddleStudent>(this, FName("GMS1"));
//查找特定类生成的对象   GetObjectsOfClass
TArray<UObject*> ObjectResults;
GetObjectsOfClass(UGoodMiddleStudent::StaticClass(), ObjectResults, false);
for(UObject* ObjectResult : ObjectResults)
{
   UE_LOG(LogTemp, Warning, TEXT("UGoodMiddleStudent::StaticClass's Object has %s"), *ObjectResult->GetName());
}

根据字符串查找类

//根据字符串查找相应的类
UClass* FinderClass = FindObject<UClass>(ANY_PACKAGE, *FString("MiddleStudent"), true);
if(FinderClass)
{
   UE_LOG(LogTemp, Warning, TEXT("Class with name:UMiddleStudent has finded"));
}

根据字符串查找枚举

//根据字符串查找相应的枚举
UEnum* FinderEnum = FindObject<UEnum>(ANY_PACKAGE, *FString("EnumName"), true);
if(FinderEnum)
{
   UE_LOG(LogTemp, Warning, TEXT("Enum with name:EnumName has finded"));

   //遍历枚举项名称
   for(int32 Index = 0; Index < FinderEnum->NumEnums(); ++Index)
   {
      FString FindedEnumItemName = FinderEnum->GetNameStringByIndex(Index);
      UE_LOG(LogTemp, Warning, TEXT("EnumName's Property has %s"), *FindedEnumItemName);
   }
}

根据字符串查找类方法

//根据名称查找类方法
UE_LOG(LogTemp, Log, TEXT("-----------------------------------------------"));
UFunction* Func1 = StudentClass->FindFunctionByName("Study", EIncludeSuperFlag::ExcludeSuper);
FString FunctionName = Func1->GetName();
UE_LOG(LogTemp, Warning, TEXT("类方法为:%s"), *FunctionName);

根据字符串查找蓝图类

这里找到通过字符串找到蓝图类后,通过这个变量获取到蓝图实例类----------->static_cast<UClass*>(WidgetBP->GeneratedClass)

//通过名称查找蓝图类
UE_LOG(LogTemp, Log, TEXT("-----------------------------------------------"));
UBlueprint* FinderBlueprint = FindObject<UBlueprint>(ANY_PACKAGE, *FString("BP_BlueprintClass"));
if(FinderBlueprint)
{
   UE_LOG(LogTemp, Warning, TEXT("Blueprint has finded, EnumName is %s"), *FinderBlueprint->GetName());

   //判断该类是蓝图类,还是Native类(Native就是C++类的意思)
   if(FinderBlueprint->IsNative())
   {
      UE_LOG(LogTemp, Warning, TEXT("Blueprint is NativeClass"));
   }else
   {
      UE_LOG(LogTemp, Warning, TEXT("Blueprint is BlueprintClass"));
   }
   //蓝图里面类设置的Native选上的意思是打包的时候转为C++类
}

获取所有的类

//遍历所有类
UE_LOG(LogTemp, Log, TEXT("-----------------------------------------------"));
FString AllClassName = "";
int32 Count = 0;
for(TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt)
{
   ++Count;
   AllClassName += ClassIt->GetName() + "   ";
}
UE_LOG(LogTemp, Warning, TEXT("虚幻中,总共有%d个类"), Count);
//UE_LOG(LogTemp, Warning, TEXT("%s"), *AllClassName);
//LogTemp: Warning: 虚幻中,总共有4410个类

使用ProcessEvent调用类方法

//使用ProcessEvent调用类方法
//1、给所有方法参数分配空间并初始为0
uint8* AllFunctionParam = static_cast<uint8*>(FMemory_Alloca(Func1->ParmsSize));
FMemory::Memzero(AllFunctionParam, Func1->ParmsSize);
//2、给所有方法参数赋值
for(TFieldIterator<FProperty> IteratorOfFuncParm(Func1); IteratorOfFuncParm; ++IteratorOfFuncParm)
{
   FProperty* FunctionParam = *IteratorOfFuncParm;
   FString FuncParName = FunctionParam->GetName();
   if(FuncParName == "InWhat")
   {
      *FunctionParam->ContainerPtrToValuePtr<FString>(AllFunctionParam) = "Ball";
   }
   if(FuncParName == "Zhengxing")
   {
      *FunctionParam->ContainerPtrToValuePtr<int>(AllFunctionParam) = 5;
   }
}
//3、调用方法
StudentClass->ProcessEvent(Func1, AllFunctionParam);
//4、打印返回值
UE_LOG(LogTemp, Warning, TEXT("函数返回值为:%d"), *(AllFunctionParam + Func1->ReturnValueOffset));

使用Function.invoke()调用类方法

//使用Function.invoke()调用类函数
UE_LOG(LogTemp, Log, TEXT("-----------------------------------------------"));
UFunction* Func2 = StudentClass->FindFunctionByName("Function1", EIncludeSuperFlag::ExcludeSuper);
uint8* AllFunctionParam1 = static_cast<uint8*>(FMemory_Alloca(Func2->ParmsSize));
FMemory::Memzero(AllFunctionParam1, Func2->ParmsSize);
//2、创建FFrame
FFrame Frame(nullptr, Func2, &AllFunctionParam1);
//3、Invoke调用函数
Func2->Invoke(Student, Frame, AllFunctionParam1);
//4、获取返回值
UE_LOG(LogTemp, Warning, TEXT("函数返回值为:%d"), *(AllFunctionParam1 + Func2->ReturnValueOffset));