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));