UE4 反射 学习笔记

想让类具有反射机制,必须要有这四个要素:

1、generated.h文件

2、UCLASS()宏

3、继承自UObject

4、GENERATED_BODY()


void ABlurCharacter::BeginPlay()
{
	Super::BeginPlay();

	ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
	UClass *BlurCharacterClass = BlurCharacter->GetClass();
	FName BlurCharacterName = BlurCharacterClass->GetFName();

	GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, *BlurCharacterName.ToString());
}

这样就将类名给输出出来了 


for(UProperty *Per = BlurCharacterClass->PropertyLink; Per; Per = Per->PropertyLinkNext)
	{
		if(Per->GetCPPType() == TEXT("FString"))
		{
			UStrProperty *Str = Cast<UStrProperty>(Per); //转化为Str类型的属性
			void *Addr = Str->ContainerPtrToValuePtr<void>(BlurCharacter);  //从容器信息转变成具体值
			GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, Per->GetName() + TEXT(" ------ ") + Per->GetCPPType() +
				TEXT(" ------ ") + Str->GetPropertyValue(Addr));
            Str->SetPropertyValue(Addr, "AfterModified");
			GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, Per->GetName() + TEXT(" ------ ") + Per->GetCPPType() +
				TEXT(" ------ ") + Str->GetPropertyValue(Addr));
		}
	}
UPROPERTY()
	FString Hello = "Hello World";

获取类中FString类型的值、类型、和名称,根据代码可以看出,存储变量的数据结构是一个链表,注意,变量一定要用UPROPERTY()给包裹,不然不会将变量信息反射到链表,更不可能存取这些信息


for(TFieldIterator<UFunction> Iter(BlurCharacterClass); Iter; ++Iter)
	{
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Blue, Iter->GetName());
		for(TFieldIterator<UProperty> Iter1(*Iter); Iter1; ++Iter1)
		{
			GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Black, Iter1->GetName() + TEXT(" ------ ") + Iter1->GetCPPType());
		}
	}

同理,自己写的函数也必须加入UFUNCTION()


void ABeginInvokeGameModeBase::BeginPlay() {
	Super::BeginPlay();

	AAFloorSwitch* FloorSwitch = NewObject<AAFloorSwitch>();

	UClass* Father = FloorSwitch->GetClass()->GetSuperClass();
	FString Name = Father->GetName();
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, Name);
}
UCLASS()
class MYCTEST_API AAFloorSwitch : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AAFloorSwitch();
}

在GameMode进行获取父类,在Actor内获取被隐藏


判断一个类是否是另一个类的父类


查找一个类的所有子类,第三个参数是找是否找子类的类,是否递归去找 


AAFloorSwitch* swithc = NewObject<AAFloorSwitch>(this, FName("Tiger"));
	TArray<UObject*>	Res;
	GetObjectsOfClass(StaticClass(), Res, false);
	for (auto Actor : Res) {
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, Actor->GetName());
	}

GetObjectsOfClass():去查找实例化出来的变量的个数


UClass *FoundClass = FindObject<UClass>(ANY_PACKAGE, *FString("ABlurCharacter"), true);
if(FoundClass->IsValidLowLevel())
{
   GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Black, FoundClass->GetName());
}

通过名字去查找类名

UEnum *FoundEnum = FindObject<UEnum>(ANY_PACKAGE, *FString("EMyEnum"), true);
if(FoundEnum->IsValidLowLevel())
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Orange, FoundEnum->GetName());
}
UENUM()
enum class EMyEnum : uint8
{
	ONE,
	TWO,
	THREE
};

通过名字查找枚举

ANY_PACKAGE是代表在每一文件夹下去查找是否有这个名字的相关值


UEnum *FoundEnum = FindObject<UEnum>(ANY_PACKAGE, *FString("EMyEnum"), true);
		if(FoundEnum->IsValidLowLevel())
		{
			//GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Orange, FoundEnum->GetName());
			for(int32 Index = 0; Index < FoundEnum->NumEnums(); Index++)
			{
				FString FoundEnumChild = FoundEnum->GetNameStringByIndex(Index);
				GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Orange, FoundEnumChild);
			}
		}
UENUM()
enum class EMyEnum : uint8
{
	ONE,
	TWO,
	THREE
};

通过枚举获取枚举内所有属性名字,EMyEnum_MAX其实是用于统计枚举内最大数值的,源代码是这么写的:

int64 UEnum::GetMaxEnumValue() const
{
	int32 NamesNum = Names.Num();
	if (NamesNum == 0)
	{
		return 0;
	}

	int64 MaxValue = Names[0].Value;
	for (int32 i = 0; i < NamesNum; ++i)
	{
		int64 CurrentValue = Names[i].Value;
		if (CurrentValue > MaxValue)
		{
			MaxValue = CurrentValue;
		}
	}

	return MaxValue;
}

如何输出这个值呢:

UEnum *FoundEnum = FindObject<UEnum>(ANY_PACKAGE, *FString("EMyEnum"), true);
if(FoundEnum->IsValidLowLevel())
	{
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Orange, FString::SanitizeFloat(FoundEnum->GetMaxEnumValue()));
	}


UBlueprint *BlueprintClass = FindObject<UBlueprint>(ANY_PACKAGE, *FString("BP_MainWidget"));
if(BlueprintClass->IsValidLowLevel())
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, BlueprintClass->GetName());
}

如何通过蓝图名称找到蓝图类


UBlueprint *BlueprintClass = FindObject<UBlueprint>(ANY_PACKAGE, *FString("BP_MainWidget"));
	if(BlueprintClass->IsValidLowLevel())
	{
		GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, BlueprintClass->GetName());
		if(BlueprintClass->IsNative())
		{
			GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, TEXT("YES"));
		}else
		{
			GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, TEXT("NO"));
		}
	}

判断此类是蓝图类还是C++类,Native就是C++类


ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
UClass *BlurCharacterClass = BlurCharacter->GetClass();
for(UProperty *Per = BlurCharacterClass->PropertyLink; Per; Per = Per->PropertyLinkNext)
{
	if(Per->GetCPPType() == TEXT("FString"))
	{
		UStrProperty *Str = Cast<UStrProperty>(Per);
		FString CategoryStr = Str->GetMetaData(TEXT("Category"));
        GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, CategoryStr);
	}
}
UPROPERTY(EditAnywhere, Category = "Hello")
	FString Hello = "Hello World";

获取元数据信息


ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
UClass *BlurCharacterClass = BlurCharacter->GetClass();
for(TFieldIterator<UFunction> Iter(BlurCharacterClass); Iter; ++Iter)
	{
		uint32 Flags = Iter->FunctionFlags;
		if(Iter->GetName() == TEXT("GetMousePixel"))	
            GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Blue, FString::FromInt(Flags));	
	}
UFUNCTION(BlueprintCallable)
	FColor GetMousePixel();

 

查找到数值为75629569,那么从第一位开始看为9,只能由1和8组成,所以兼备FUNC_Final和FUNC_BlueprintCosmetic的属性,即该方法为Final方法,此方法不能被继承,且该方法不能被服务端调用

再看第二位60只能由//FUNC_与FUNC_Net组成,第一个无用,没有功能,第二个该方法可被网络复制

我们直接看第七位,为5,只能由FUNC_NetClient与FUNC_BlueprintCallable组成,第一个为该函数可在客户端进行执行,第二个就是经常用到的BlueprintCallable了,如上方代码所对应

其它位数都是依次类推

enum EFunctionFlags
{
	// Function flags.
	FUNC_Final				= 0x00000001,	// Function is final (prebindable, non-overridable function).
	FUNC_RequiredAPI			= 0x00000002,	// Indicates this function is DLL exported/imported.
	FUNC_BlueprintAuthorityOnly= 0x00000004,   // Function will only run if the object has network authority
	FUNC_BlueprintCosmetic	= 0x00000008,   // Function is cosmetic in nature and should not be invoked on dedicated servers
	// FUNC_				= 0x00000010,   // unused.
	// FUNC_				= 0x00000020,   // unused.
	FUNC_Net				= 0x00000040,   // Function is network-replicated.
	FUNC_NetReliable		= 0x00000080,   // Function should be sent reliably on the network.
	FUNC_NetRequest			= 0x00000100,	// Function is sent to a net service
	FUNC_Exec				= 0x00000200,	// Executable from command line.
	FUNC_Native				= 0x00000400,	// Native function.
	FUNC_Event				= 0x00000800,   // Event function.
	FUNC_NetResponse		= 0x00001000,   // Function response from a net service
	FUNC_Static				= 0x00002000,   // Static function.
	FUNC_NetMulticast		= 0x00004000,	// Function is networked multicast Server -> All Clients
	// FUNC_				= 0x00008000,   // unused.
	FUNC_MulticastDelegate	= 0x00010000,	// Function is a multi-cast delegate signature (also requires FUNC_Delegate to be set!)
	FUNC_Public				= 0x00020000,	// Function is accessible in all classes (if overridden, parameters must remain unchanged).
	FUNC_Private			= 0x00040000,	// Function is accessible only in the class it is defined in (cannot be overridden, but function name may be reused in subclasses.  IOW: if overridden, parameters don't need to match, and Super.Func() cannot be accessed since it's private.)
	FUNC_Protected			= 0x00080000,	// Function is accessible only in the class it is defined in and subclasses (if overridden, parameters much remain unchanged).
	FUNC_Delegate			= 0x00100000,	// Function is delegate signature (either single-cast or multi-cast, depending on whether FUNC_MulticastDelegate is set.)
	FUNC_NetServer			= 0x00200000,	// Function is executed on servers (set by replication code if passes check)
	FUNC_HasOutParms		= 0x00400000,	// function has out (pass by reference) parameters
	FUNC_HasDefaults		= 0x00800000,	// function has structs that contain defaults
	FUNC_NetClient			= 0x01000000,	// function is executed on clients
	FUNC_DLLImport			= 0x02000000,	// function is imported from a DLL
	FUNC_BlueprintCallable	= 0x04000000,	// function can be called from blueprint code
	FUNC_BlueprintEvent		= 0x08000000,	// function can be overridden/implemented from a blueprint
	FUNC_BlueprintPure		= 0x10000000,	// function can be called from blueprint code, and is also pure (produces no side effects). If you set this, you should set FUNC_BlueprintCallable as well.
	// FUNC_				= 0x20000000,	// unused.
	FUNC_Const				= 0x40000000,	// function can be called from blueprint code, and only reads state (never writes state)
	FUNC_NetValidate		= 0x80000000,	// function must supply a _Validate implementation

	// Combinations of flags.
	FUNC_FuncInherit        = FUNC_Exec | FUNC_Event | FUNC_BlueprintCallable | FUNC_BlueprintEvent | FUNC_BlueprintAuthorityOnly | FUNC_BlueprintCosmetic,
	FUNC_FuncOverrideMatch	= FUNC_Exec | FUNC_Final | FUNC_Static | FUNC_Public | FUNC_Protected | FUNC_Private,
	FUNC_NetFuncFlags       = FUNC_Net | FUNC_NetReliable | FUNC_NetServer | FUNC_NetClient | FUNC_NetMulticast,
	FUNC_AccessSpecifiers	= FUNC_Public | FUNC_Private | FUNC_Protected,

	FUNC_AllFlags		= 0xFFFFFFFF,
};

ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
UClass *BlurCharacterClass = BlurCharacter->GetClass();
uint32 ClassFlags = BlurCharacterClass->ClassFlags;
GEngine->AddOnScreenDebugMessage(-1, 10.f ,FColor::Red, FString::FromInt(ClassFlags));

同理:这样就可以获取一些与类相关的信息

enum EClassFlags
{
	/** @name Base flags */
	//@{
	CLASS_None				  = 0x00000000,
	/** Class is abstract and can't be instantiated directly. */
	CLASS_Abstract            = 0x00000001,
	/** Save object configuration only to Default INIs, never to local INIs. Must be combined with CLASS_Config */
	CLASS_DefaultConfig		  = 0x00000002,
	/** Load object configuration at construction time. */
	CLASS_Config			  = 0x00000004,
	/** This object type can't be saved; null it out at save time. */
	CLASS_Transient			  = 0x00000008,
	/** Successfully parsed. */
	CLASS_Parsed              = 0x00000010,
	/** */
	//CLASS_                  = 0x00000020,
	/** All the properties on the class are shown in the advanced section (which is hidden by default) unless SimpleDisplay is specified on the property */
	CLASS_AdvancedDisplay	  = 0x00000040,
	/** Class is a native class - native interfaces will have CLASS_Native set, but not RF_MarkAsNative */
	CLASS_Native			  = 0x00000080,
	/** Don't export to C++ header. */
	CLASS_NoExport            = 0x00000100,
	/** Do not allow users to create in the editor. */
	CLASS_NotPlaceable        = 0x00000200,
	/** Handle object configuration on a per-object basis, rather than per-class. */
	CLASS_PerObjectConfig     = 0x00000400,
	
	/** pointers to this class default to weak. */
	CLASS_PointersDefaultToWeak = 0x00000800,
	
	/** Class can be constructed from editinline New button. */
	CLASS_EditInlineNew		  = 0x00001000,
	/** Display properties in the editor without using categories. */
	CLASS_CollapseCategories  = 0x00002000,
	/** Class is an interface **/
	CLASS_Interface           = 0x00004000,
	/**  Do not export a constructor for this class, assuming it is in the cpptext **/
	CLASS_CustomConstructor   = 0x00008000,
	/** all properties and functions in this class are const and should be exported as const */
	CLASS_Const			      = 0x00010000,

	/** pointers to this class default to weak. */
	CLASS_PointersDefaultToAutoWeak = 0x00020000,
	
	/** Indicates that the class was created from blueprint source material */
	CLASS_CompiledFromBlueprint  = 0x00040000,

	/** Indicates that only the bare minimum bits of this class should be DLL exported/imported */
	CLASS_MinimalAPI	      = 0x00080000,
	
	/** Indicates this class must be DLL exported/imported (along with all of it's members) */
	CLASS_RequiredAPI	      = 0x00100000,

	/** Indicates that references to this class default to instanced. Used to be subclasses of UComponent, but now can be any UObject */
	CLASS_DefaultToInstanced  = 0x00200000,

	/** Indicates that the parent token stream has been merged with ours. */
	CLASS_TokenStreamAssembled  = 0x00400000,
	/** Class has component properties. */
	CLASS_HasInstancedReference= 0x00800000,
	/** Don't show this class in the editor class browser or edit inline new menus. */
	CLASS_Hidden			  = 0x01000000,
	/** Don't save objects of this class when serializing */
	CLASS_Deprecated		  = 0x02000000,
	/** Class not shown in editor drop down for class selection */
	CLASS_HideDropDown		  = 0x04000000,
	/** Class settings are saved to <AppData>/..../Blah.ini (as opposed to CLASS_DefaultConfig) */
	CLASS_GlobalUserConfig	  = 0x08000000,
	/** Class was declared directly in C++ and has no boilerplate generated by UnrealHeaderTool */
	CLASS_Intrinsic			  = 0x10000000,
	/** Class has already been constructed (maybe in a previous DLL version before hot-reload). */
	CLASS_Constructed		  = 0x20000000,
	/** Indicates that object configuration will not check against ini base/defaults when serialized */
	CLASS_ConfigDoNotCheckDefaults = 0x40000000,
	/** Class has been consigned to oblivion as part of a blueprint recompile, and a newer version currently exists. */
	CLASS_NewerVersionExists  = 0x80000000,

	//@}


	/** @name Flags to inherit from base class */
	//@{
	CLASS_Inherit           = CLASS_Transient | CLASS_DefaultConfig | CLASS_Config | CLASS_PerObjectConfig | CLASS_ConfigDoNotCheckDefaults | CLASS_NotPlaceable
							| CLASS_PointersDefaultToAutoWeak | CLASS_PointersDefaultToWeak | CLASS_Const
							| CLASS_HasInstancedReference | CLASS_Deprecated | CLASS_DefaultToInstanced | CLASS_GlobalUserConfig,

	/** these flags will be cleared by the compiler when the class is parsed during script compilation */
	CLASS_RecompilerClear   = CLASS_Inherit | CLASS_Abstract | CLASS_NoExport | CLASS_Native | CLASS_Intrinsic | CLASS_TokenStreamAssembled,

	/** these flags will be cleared by the compiler when the class is parsed during script compilation */
	CLASS_ShouldNeverBeLoaded   = CLASS_Native | CLASS_Intrinsic | CLASS_TokenStreamAssembled,

	/** these flags will be inherited from the base class only for non-intrinsic classes */
	CLASS_ScriptInherit		= CLASS_Inherit | CLASS_EditInlineNew | CLASS_CollapseCategories,
	//@}

	/** This is used as a mask for the flags put into generated code for "compiled in" classes. */
	CLASS_SaveInCompiledInClasses = 
		CLASS_Abstract | 
		CLASS_DefaultConfig |
		CLASS_GlobalUserConfig |
		CLASS_Config |
		CLASS_Transient |
		CLASS_Native |
		CLASS_NotPlaceable |
		CLASS_PerObjectConfig |
		CLASS_ConfigDoNotCheckDefaults |
		CLASS_PointersDefaultToWeak |
		CLASS_EditInlineNew |
		CLASS_CollapseCategories |
		CLASS_Interface |
		CLASS_PointersDefaultToAutoWeak |
		CLASS_DefaultToInstanced |
		CLASS_HasInstancedReference |
		CLASS_Hidden |
		CLASS_Deprecated |
		CLASS_HideDropDown |
		CLASS_Intrinsic |
		CLASS_AdvancedDisplay |
		CLASS_Const |
		CLASS_MinimalAPI |
		CLASS_RequiredAPI,

	CLASS_AllFlags			= 0xFFFFFFFF,
};

ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
UClass *BlurCharacterClass = BlurCharacter->GetClass();
for(TObjectIterator<UClass> ClassIter; ClassIter; ++ClassIter)
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, ClassIter->GetName());
}

获取所有的类


ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
UClass *BlurCharacterClass = BlurCharacter->GetClass();
UFunction *PixelStr = BlurCharacterClass->FindFunctionByName("GetMousePixel");
GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Yellow, PixelStr->GetName());

通过方法名字查找到方法


ABlurCharacter *BlurCharacter = NewObject<ABlurCharacter>();
UClass *BlurCharacterClass = BlurCharacter->GetClass();
UFunction *PixelMethod = BlurCharacterClass->FindFunctionByName("GainMousePixel", EIncludeSuperFlag::ExcludeSuper);
if(PixelMethod->IsValidLowLevel())
{
	//分配空间并初始化为0
	uint8* LocSize = static_cast<uint8*>(FMemory_Alloca(PixelMethod->ParmsSize));//获取参数所占的空间大小来进行一个空间分配
	FMemory::Memzero(LocSize, PixelMethod->ParmsSize);
	//给方法内参数赋值
	for(TFieldIterator<UProperty> Pro(PixelMethod); Pro; ++Pro)
	{
		if(Pro->GetName() == FString("num"))
		{
			*Pro->ContainerPtrToValuePtr<FString>(LocSize) = "5";
		}
	}
    //使用ProcessEvent调用方法
	BlurCharacter->ProcessEvent(PixelMethod, LocSize);
}
void ABlurCharacter::GainMousePixel(FString num)
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Green, num);
}

使用ProcessEvent调用函数


AMyProjectPawn* MyProjectPawn = NewObject<AMyProjectPawn>();
UClass* BlurCharacterClass = MyProjectPawn->GetClass();
UFunction* PixelMethod = BlurCharacterClass->FindFunctionByName("GainMousePixel", EIncludeSuperFlag::ExcludeSuper);
if (PixelMethod->IsValidLowLevel()) {
	uint8* AllFuncParam = static_cast<uint8*>(FMemory_Alloca(PixelMethod->ParmsSize));
	FMemory::Memzero(AllFuncParam, PixelMethod->ParmsSize);
	FFrame Frame(nullptr, PixelMethod, &AllFuncParam);
	PixelMethod->Invoke(MyProjectPawn, Frame, &AllFuncParam + PixelMethod->ReturnValueOffset);
}
void AMyProjectPawn::GainMousePixel(FString num)
{
	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Green, TEXT("VALUE = ") + num);
}

使用Invoke调用函数


反射数据的基类:

class COREUOBJECT_API UField : public UObject
{
	DECLARE_CASTED_CLASS_INTRINSIC(UField, UObject, CLASS_Abstract, TEXT("/Script/CoreUObject"), CASTCLASS_UField)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值