ef怎么把字段设置成枚举类型_《InsideUE4》UObject(十三)类型系统-反射实战

本文介绍了如何在UE4中利用反射操作EF字段设置为枚举类型,并展示了如何在运行时动态修改类型。内容包括获取类型对象、遍历字段、查看继承、反射调用函数以及运行时修改类型等实战技巧,帮助开发者深入理解UE4的类型系统和反射机制。
摘要由CSDN通过智能技术生成

e740f8026795476c6a46fd1efa9a2b60.png
爱,代码+喵星人

引言

上篇章节总结了类型系统的最后一些小知识点,为了免于说都是纯理论知识,本篇我们来讲一些利用反射的例子。

获取类型对象

如果想获取到程序里定义的所有的class,方便的方法是:

TArray<UObject*> result;
GetObjectsOfClass(UClass::StaticClass(), result);   //获取所有的class和interface
GetObjectsOfClass(UEnum::StaticClass(), result);   //获取所有的enum
GetObjectsOfClass(UScriptStruct::StaticClass(), result);   //获取所有的struct

GetObjectsOfClass是UE4已经写好的一个很方便的方法,可以获取到属于某个UClass*下面的所有对象。因此如果用UClass::StaticClass()本身,就可以获得程序里定义的所有class。值得注意的是,UE4里的接口是有一个配套的UInterface对象来存储元数据信息,它的类型也是用UClass*表示的,所以也会获得interface。根据前文,enum会生成UEnum,struct会生成UScriptStruct,所以把参数换成UEnum::StaticClass()就可以获得所有的UEnum*对象了,UScriptStruct::StaticClass()就是所有的UScriptStruct*了,最后就可以根据这些类型对象来反射获取类型信息了。

而如果要精确的根据一个名字来查找某个类型对象,就可以用UE4里另一个方法:

template< class T > 
inline T* FindObject( UObject* Outer, const TCHAR* Name, bool ExactClass=false )
{
    
    return (T*)StaticFindObject( T::StaticClass(), Outer, Name, ExactClass );
}

UClass* classObj=FindObject<UClass>(ANY_PACKAGE,"MyClass");   //获得表示MyClass的UClass*

这样就可以轻易的获得不同类型的对象。FindObject内部的原理在下大章节内存管理再讲述。

遍历字段

在获取到了一个类型对象后,就可以用各种方式去遍历查找内部的字段了。为此,UE4提供了一个方便的迭代器TFieldIterator<T>,可以通过它筛选遍历字段。

const UStruct* structClass; //任何复合类型都可以
//遍历属性
for (TFieldIterator<UProperty> i(structClass); i; ++i)
{
    
    UProperty* prop=*i; 
}
//遍历函数
for (TFieldIterator<UFunction> i(structClass); i; ++i)
{
    
    UFunction* func=*i; 
    //遍历函数的参数
    for (TFieldIterator<UProperty> i(func); i; ++i)
    {
    
        UProperty* param=*i; 
        if( param->PropertyFlags & CPF_ReturnParm ) //这是返回值
        {
    

        }
    }
}
//遍历接口
const UClass* classObj; //只有UClass才有接口
for (const FImplementedInterface& ii : classObj->Interfaces)
{
    
    UClass* interfaceClass = ii.Class;
}

给模板参数T传UFunction就可以获得类型下的所有函数,通过这也可以遍历获得UFunction下的参数列表。当然TFieldIterator也可以再传其他参数的控制是否包含基类的字段、是否包含废弃的字段、是否包含接口里的字段。TFieldIterator的内部实现其实也挺简单的,一是通过SuperStruct来获得Super,二是通过Interfaces来获得实现的接口,三是用Field->Next来遍历字段。信息数据都是全的,迭代遍历就简单了。

遍历枚举的字段也很简单:

const UEnum* enumClass;
for (int i = 0; i < enumClass->NumEnums(); ++i)
{
    
    FName name = enumClass->GetNameByIndex(i);
    int value = enumClass->GetValueByIndex(i);
}

还有遍历元数据的:

#if WITH_METADATA
const UObject* obj;//可以是任何对象,但一般是UField才有值
UMetaData* metaData = obj->GetOutermost()->GetMetaData();
TMap<FName, FString>* keyValues = metaData->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值