UE4 C++ 利用反射获取到类、类的成员

3 篇文章 0 订阅

以下内容,如果已经有实例指针,都推荐使用GetClass()来获取到其所属UClass。
StaticClass()只能获取当前指针类型的UClass,GetClass()可以获取到其最顶层的UClass

!!!强烈推荐GetClass()代替StaticClass()

一、获取到特定类的对象实例

1.1、GetObjectsOfClass

GetObjectsOfClass(类型::GetStaticClass(),存储结果的数组);

	TArray<UObject*> Objs;
	GetObjectsOfClass(UClass::StaticClass(), Objs);

	TArray<UObject*> ActorObjs;
	GetObjectsOfClass(AActor::StaticClass(), ActorObjs);

	TArray<UObject*> StructObjs;
	GetObjectsOfClass(UScriptStruct::StaticClass(), StructObjs);

	TArray<UObject*> EnumObjs;
	GetObjectsOfClass(UEnum::StaticClass(), EnumObjs);
	
	//这里是IMyInterface对应的UMyInterface
	TArray<UObject*> Interfaces;
	GetObjectsOfClass(UMyInterface::StaticClass(), Interfaces);

1.2、FindObject

通过名字就可以查找
FindObject<UClass>(要搜索的区域,类名);

UClass* ActorRef = FindObject<UClass>(ANY_PACKAGE,*FString("AActor"));
//获取到UEnum
UEnum* EnumPtr=FindObject<UEnum>((UObject*)ANY_PACKAGE,*FString("EMyEnum"),true);
EnumPtr->GetEnumName((int32)0));	//获取到第0个枚举的名字

1.3 GetAllActorsOfClass

仅支持AActor子类

TArray<AActor*> Actors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(),AMyActor::StaticClass(),Actors);

二、获取到类的成员

2021年08月18日更新:ue4.26补充

2.0 UE4.26更新后UProperty类型更换为了FProperty,基本逻辑不变,简单演示:

for (TFieldIterator<FProperty> it(GetClass());it;++it)
	{
		FStructProperty* Value = CastField<FStructProperty>(*it);
		FGameplayAttributeData* Param = Value->ContainerPtrToValuePtr<FGameplayAttributeData>(this);
		
		//FGameplayAttribute* tmpAttr= static_cast<FGameplayAttribute*>(Param);
		if (Param)
		{
			//UE_LOG(LogTemp,Warning,TEXT("Sucess"));
			tmpAttributes.Add(*Param);
		}
	}

以下是原内容

2.1 常见成员变量(int float string)

MyStruct
USTRUCT(Blueprintable)
struct FMyStruct {
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly)
		TArray<UBoxComponent*> ArrayComponent;

	UPROPERTY(EditDefaultsOnly)
		TSet<AActor*> SetComponent;

	UPROPERTY(EditDefaultsOnly,BlueprintReadOnly)
		float FloatValue;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
		FString StrValue;
};
获取MyStruct中名为"FloatValue"的值并修改
for (TFieldIterator<UProperty> it(MyStruct.StaticStruct());it;++it)
	{
		//
		if (it->GetName()=="FloatValue")
		{
			UFloatProperty* Value = Cast<UFloatProperty>(*it);
			if (Value->HasAllPropertyFlags(CPF_BlueprintReadOnly))
			{
				UE_LOG(LogTemp, Log, TEXT("Get FloatValue success"));
				//将UScriptStruct里的链接器连入MyStruct对应变量的真实地址中
				void* Param = Value->ContainerPtrToValuePtr<void*>(&MyStruct);
				//给真实地址中的Param赋值为4
				Value->SetPropertyValue(Param, 4.f);
				//获取到该地址的值
				Value->GetPropertyValue(Param);
				//获取到Flag
				EPropertyFlags Flags = Value->GetPropertyFlags();

				//获取到容器中的第0个值
				//Value->GetPropertyValue_InContainer(Param,0);
			}	
		}
		
		//使用UE4的TEXT导入导出实现变量的赋值与传递
		if (it->GetName() == "StrValue")
		{
			UStrProperty* str = Cast<UStrProperty>(*it);
			if (str)
			{
				//导入Text并赋值
				str->ImportText(TEXT("B"), str->ContainerPtrToValuePtr<void*>(&MyStruct), EPropertyPortFlags::PPF_None, nullptr);
				//导出为Text
				str->ExportTextItem(TempStr, str->ContainerPtrToValuePtr<void*>(&MyStruct), nullptr, nullptr, EPropertyPortFlags::PPF_None, nullptr);
			}
		}
	}

2.2 Object子类属性

获取到UObject的子类类型变量并赋值到C++变量中

第一步:获取到所属类相应的UClass
第二步:通过变量名寻找UClass的对应属性
第三步:将找到的属性转换为对应的Object*指针

	//绑定Anim到AnimRef(Anim为C++成员变量,AnimRef为蓝图成员变量,两者皆为UWidgetAnimtion)
	//GetClass可以获取到顶层的类的UClass,而不是当前C++类的UClass,建议不使用StaticClass
	if (UObjectProperty* AnimRef = Cast<UObjectProperty>(GetClass()->FindPropertyByName(FName("AnimRef"))))
	{
		//this改为你要获取的那个蓝图类的引用
		Anim = Cast<UWidgetAnimation>(AnimRef->GetObjectPropertyValue_InContainer(this));
		if (Anim==nullptr)
		{
			UE_LOG(LogTemp, Warning, TEXT("Anim Read Failed!"));
		}
	}

2.3 成员函数,并获取到函数中的所有参数

	for (TFieldIterator<UFunction> i(AMyActor::StaticClass());i;++i)
	{
		for (TFieldIterator<UProperty> j(*i);j;++j)
		{
			if (j->PropertyFlags & CPF_ReturnParm)
			{
				UE_LOG(LogTemp, Log, TEXT("Find return param:%s"), *i->GetName());
			}
		}
	}

2.4 接口

	for (int i=AMyActor::StaticClass()->Interfaces.Num();i;--i)
	{
		FImplementedInterface* f = &(AMyActor::StaticClass()->Interfaces[i-1]);
	}

2.5 判断该类是否继承了某一接口

	//注意:这里是UMyInterface而不是IMyInterface
	AActor::StaticClass()->ImplementsInterface(UMyInterface::StaticClass());

三、简单应用:将A的数据拷贝到B

if (InitData)
	{
		TMap<FString,void*> DataMap;
		for (TFieldIterator<FProperty> it(InitData->GetClass());it;++it)
		{
			// if (it->HasAnyPropertyFlags(EPropertyFlags::CPF_ExposeOnSpawn))
			// {
			//
			// }
			void* Param= it->ContainerPtrToValuePtr<void>(InitData);
			DataMap.Add(it->GetName(),Param);
		}
		for (TFieldIterator<FProperty> it(GetClass());it;++it)
		{
			// if (it->HasAnyPropertyFlags(EPropertyFlags::CPF_ExposeOnSpawn))
			// {
			// 	
			// }
			if (void** valuePtr= DataMap.Find(it->GetName()))
			{
				void* Param= it->ContainerPtrToValuePtr<void>(this);
				it->CopySingleValue(Param,*valuePtr);
			}
		}
		
	}
  • 17
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值