Skip to content

Instantly share code, notes, and snippets.

@badforlabor
Last active October 20, 2025 13:23
Show Gist options
  • Select an option

  • Save badforlabor/a01474ead3dcd8ebc09297a1059b4af3 to your computer and use it in GitHub Desktop.

Select an option

Save badforlabor/a01474ead3dcd8ebc09297a1059b4af3 to your computer and use it in GitHub Desktop.
UnrealEngine. Set values using Property System (Reflection)
// 反射工具
class FReflectionHelper
{
public:
template <typename T>
static T GetDefault()
{
static T t;
return t;
}
static bool HasAttr(UObject* Ptr, const char* AttrName)
{
if (!Ptr)
{
return false;
}
return Ptr->GetClass()->FindPropertyByName(AttrName) != nullptr;
}
static int GetValue(UObject* Ptr, const char* AttrName)
{
if (Ptr)
{
FIntProperty* IntProp = Cast<FIntProperty>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (IntProp)
{
void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(Ptr);
return IntProp->GetPropertyValue(PropertyAddress);
}
}
return 0;
}
static void SetValue(UObject* Ptr, const char* AttrName, int Value)
{
if (Ptr)
{
FIntProperty* IntProp = Cast<FIntProperty>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (IntProp)
{
void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(
Ptr);
IntProp->SetPropertyValue(PropertyAddress, Value);
}
}
}
template <typename T>
static bool HasAttr(UObject* Ptr, const char* AttrName)
{
if (!Ptr)
{
return false;
}
return Cast<T>(Ptr->GetClass()->FindPropertyByName(AttrName)) != nullptr;
}
// 如 int, FIntProperty
template <typename PropType>
static typename PropType::TCppType TGetValue(UObject* Ptr, const char* AttrName)
{
if (Ptr)
{
PropType* IntProp = Cast<PropType>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (IntProp)
{
void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(Ptr);
return IntProp->GetPropertyValue(PropertyAddress);
}
}
// static typename PropType::TCppType Ret;
return GetDefault<typename PropType::TCppType>();
}
// 如 int, FIntProperty
template <typename PropType>
static void TSetValue(UObject* Ptr, const char* AttrName, const typename PropType::TCppType& Value)
{
if (Ptr)
{
PropType* IntProp = Cast<PropType>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (IntProp)
{
void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(Ptr);
IntProp->SetPropertyValue(PropertyAddress, Value);
}
}
}
// 如 int, FIntProperty
template <typename PropType>
static TArray<typename PropType::TCppType> TGetArrValue(UObject* Ptr, const char* AttrName)
{
TArray<typename PropType::TCppType> Ret;
if (Ptr)
{
FArrayProperty* ArrayProperty = Cast<FArrayProperty>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (ArrayProperty)
{
PropType* StrProp = CastField<PropType>(ArrayProperty->Inner);
if (StrProp)
{
void* PropertyAddress = ArrayProperty->ContainerPtrToValuePtr<void>(Ptr);
FScriptArrayHelper ArrayHelper(ArrayProperty, PropertyAddress);
const int32 NumElements = ArrayHelper.Num();
for (int32 Index = 0; Index < NumElements; Index++)
{
void* ArrayData = ArrayHelper.GetRawPtr(Index);
if (ArrayData)
{
Ret.Add(StrProp->GetPropertyValue(ArrayData));
}
}
}
}
}
return Ret;
}
// 如 int, FIntProperty
template <typename PropType>
static void TAddArrValue(UObject* Ptr, const char* AttrName, const typename PropType::TCppType& V)
{
if (Ptr)
{
FArrayProperty* ArrayProperty = Cast<FArrayProperty>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (ArrayProperty)
{
PropType* StrProp = CastField<PropType>(ArrayProperty->Inner);
if (StrProp)
{
void* ArrPropertyAddress = ArrayProperty->ContainerPtrToValuePtr<void>(Ptr);
FScriptArrayHelper ArrayHelper(ArrayProperty, ArrPropertyAddress);
int Idx = -1;
if (StrProp->PropertyFlags & CPF_IsPlainOldData)
{
Idx = ArrayHelper.AddUninitializedValue();
}
else
{
Idx = ArrayHelper.AddValue();
}
if (Idx >= 0)
{
void* ArrayData = ArrayHelper.GetRawPtr(Idx);
if (ArrayData)
{
StrProp->SetPropertyValue(ArrayData, V);
}
}
}
}
}
}
// 如 int, FIntProperty
template <typename PropType>
static void TSetArrValue(UObject* Ptr, const char* AttrName, const TArray<typename PropType::TCppType>& V)
{
if (Ptr)
{
FArrayProperty* ArrayProperty = Cast<FArrayProperty>(Ptr->GetClass()->FindPropertyByName(AttrName));
if (ArrayProperty)
{
PropType* StrProp = CastField<PropType>(ArrayProperty->Inner);
if (StrProp)
{
void* ArrPropertyAddress = ArrayProperty->ContainerPtrToValuePtr<void>(Ptr);
FScriptArrayHelper ArrayHelper(ArrayProperty, ArrPropertyAddress);
if (StrProp->PropertyFlags & CPF_IsPlainOldData)
{
ArrayHelper.EmptyAndAddUninitializedValues(V.Num());
}
else
{
ArrayHelper.EmptyAndAddValues(V.Num());
}
for (int i = 0; i < V.Num(); i++)
{
void* ArrayData = ArrayHelper.GetRawPtr(i);
if (ArrayData)
{
StrProp->SetPropertyValue(ArrayData, V[i]);
}
}
}
}
}
}
#if false
template <typename PropType>
struct Helper
{
typedef typename PropType::TCppType ValueType;
static void Set(UObject* Ptr, const char* AttrName, const ValueType& Value)
{
TSetValue<PropType>(Ptr, AttrName, Value);
}
};
#endif
static void TestAll(UObject* Ptr)
{
{
TAddArrValue<FIntProperty>(Ptr, "arr1", 0);
TAddArrValue<FStrProperty>(Ptr, "arr1", TEXT("123"));
auto Ret = TGetArrValue<FIntProperty>(Ptr, "arr1");
TSetArrValue<FIntProperty>(Ptr, "arr1", Ret);
}
{
HasAttr(Ptr, "v1");
TSetValue<FIntProperty>(Ptr, "v1", 0);
auto Ret = TGetValue<FIntProperty>(Ptr, "v1");
}
{
HasAttr(Ptr, "v2");
TSetValue<FStrProperty>(Ptr, "v2", "123");
auto Ret = TGetValue<FStrProperty>(Ptr, "v2");
}
{
#if false
Helper<FStrProperty>::Set(Ptr, "v2", "123");
#endif
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment