通过反射获取类的名称
通过继承自UObject的类可以获取到类名。
假如声明了一个名为Player的类,并在GameMode中实例化了一个Player,则可以通过GatName获取到类的名称。
Player的声明:
1 | UCLASS() |
在GameMode中实例化:
1 | AProjectGameMode::AProjectGameMode() |
选择GameMode即可看到日志输出:Player Name is :UPlayer
获取与设置类字符串属性
现在UPlayer类中声明一个FString,UPROPERTY宏是必要的:
1 | UPROPERTY() |
同样在GameMode中进行操作:
1 | for (FProperty* Property = PlayerClass->PropertyLink; Property; Property = Property->PropertyLinkNext) { |
便能在日志中看到:”The PlayerClass’s Name is :TestName ,Type is :FString ,Value is :MyName”
现在来设置这个属性,只需将Get改为Set,并赋入新值:
1 | StringProperty->SetPropertyValue(Addr,TEXT("NewName")); |
同样可以在日志中看到:”The PlayerClass’s Name is :TestName ,Type is :FString ,Value is :NewName”
获取类的函数
操作方法类似,需要一个迭代器来获取类的成员函数:
1 | for(TFieldIterator<UFuntion> FunctionIterator(PlayerClass);FunctionIterator;++FunctionIterator){ |
执行后在日志中可以看到:”The PlayerClass’s Functions’ name is :ExecuteUbergraph”
这是UE为类默认添加的一个方法,我们在类中添加一个自己的函数:
1 | UFUNCTION() |
随后再次执行,便可以看到一条额外的日志:”The PlayerClass’s Functions’ name is :TestFunction”
除了能够获取名称外,还可以获取参数与返回值类型,首先对TestFunction进行修改:
1 | UFUNCTION() |
随后嵌套一个迭代器进行访问:
1 | for(TFieldIterator<FProperty> ParamIterator(*FunctionIterator);ParamIterator;++ParamIterator){ |
在日志中可以看到函数的返回值被作为参数信息获取到,类型为int32,名称为ReturnValue。
还可以获取到参数的标记(Flags),标记是一个枚举类型,以十六进制表示,并且可以由多个枚举组合而成,可以将得到的十六进制数按位数拆分查找即可知道参数的类型,
在内层循环中添加如下代码来查看参数类型:
1 | EPropertyFlags ParamFlags=ParamIterator->GetPropertyFlags(); |
获取父类名称
首先新建一个类,继承自PlayerObject,并命名为MainPlayerObject,同样在GameMode中进行操作,不同的是,要通过GetSuperClass获取父类名称:
1 | UMainPlayerObject* MainPlayer=NewObject<UMainPlayerObject>(); |
执行后便可在日志中看到:”The MainPlayerObject’s SuperClass’s name is :PlayerObject”
判断子类关系
在虚幻中可以判断一个类是否为另一个类的子类,通过AClass.IsChildOf(BClass)即可判断:
1 | if(MainPlayerClass->IsChildOf(PlayerObject)){ |
执行后可以在日志中看到输出:”MainPlayerObject is a Child of PlayerObject”
此外还可以查看一个类的所有子类,通过GetDerivedClasses()实现
函数声明为:void GetDerivedClasses(const UClass* ClassToLookFor, TArray<UClass*>& Results, bool bRecursive)
第一个参数为需要查找的类,第二个参数为查找结果,第三个参数为是否递归查找子类,即是否查找子类的子类
假如要查找PlayerObject类的所有子类,则可以写成:
1 | TArray<UClass*> DerivedClasses; |
执行后便可在日志中看到:”The DerivedClass’s name is :MainPlayerObject”
查找类生成的对象
操作方法与查找子类的方法类似,将UClass改为UObject即可:
我们去查找UMainPlayerObject的实例化对象
1 | UMainPlayerObject* MainPlayer=NewObject<UMainPlayerObject>(this,TEXT("MainPlayerObject")); |
执行后便可在日志中看到输出:”The UMainPlayerObject’s instance’s name is :MainPlayerObject”
查找功能
可以通过字符串查找某一类是否存在,通过FindObeject函数实现
来查找UMainPlayerObject类是否存在:
1 | //类名称不加前缀,不需要写成UMainPlayerObject |
执行后便可在日志中看到输出:”The UMainPlayerObject class is exist”
对于蓝图类的查找也是一样的,先新建一个蓝图,并命名为BP_Actor
1 | UBlueprint* FindedBlueprint=FindObject<UBlueprint>(ANY_PACKAGE,TEXT("BP_Actor"),true); |
同样执行后可以在日志中看到:”The BP_Actor blueprint is exist”
还可以进一步操作,比如想知道查找到的这个类是否为Native类,可以通过FindedClass->IsNative()来判断
通过FindFunctionByName来查找某个类的方法
- 本文作者: KongXinQing
- 本文链接: https://13114987559.github.io/2023/11/08/essay/虚幻反射的基础应用/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!