scha
(scha)
February 1, 2017, 12:14pm
1
Is it possible to list all UProperties of an object at runtime? Or find an UProperty by its name?
Also, is it possible to read/write an UProperty?
Example, suppose you have a bool UProperty called Flag.
What I want to do is something like:
name="Flag";
prop = obj.GetProperty(name);
prop.SetValue(true);
iniside
(iniside)
February 1, 2017, 12:43pm
2
It’s not that easy as you want but it’s possible.
For more reference look at JsonUtilities module.
Unfortunately not in three lines.
But something like this may work (untested)
UObject* Object = ...; //assign your object instance which has the Flag member here!
UClass* Class = Object->GetClass();
static FName FlagPropertyName = TEXT("Flag");
for (TFieldIterator<UProperty> PropertyIterator(Class); PropertyIterator; ++PropertyIterator)
{
UProperty* Property = *PropertyIterator;
FName const PropertyName = Property->GetFName();
if ( PropertyName == FlagPropertyName )
{
UBoolProperty* BoolProperty = Cast<BoolProperty>(Property);
if (BoolProperty)
{
BoolProperty->SetPropertyValue((void*) Object, true);
break;
}
}
}
scha
(scha)
February 1, 2017, 3:35pm
4
Thank you very much you both! So, as I understand I also can use “FindPropertyByName”. It’s a method of UStruct, which is a parent of UClass.
Like this:
UProperty* Property = class->FindPropertyByName(FName);
if (UBoolProperty *BoolProperty = Cast<UBoolProperty>(Property))
{
BoolProperty->SetPropertyValue((void*)object, true);
}
scha
(scha)
February 2, 2017, 12:21pm
5
For some reason it crashes the editor. I tried both ways, FindPropertyByName and the iterator and every time it crashes.
Here’s my code:
//.h
UCLASS()
class TEST415_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static void SetPropertyFlag(UObject* object, bool value);
};
//.cpp
void UMyBlueprintFunctionLibrary::SetPropertyFlag(UObject* object, bool value)
{
static FName FlagPropertyName = TEXT("Flag");
UClass *cl = object->GetClass();
if (cl)
{
for (TFieldIterator<UProperty> PropertyIterator(cl); PropertyIterator; ++PropertyIterator)
{
UProperty* Property = *PropertyIterator;
FName const PropertyName = Property->GetFName();
if (PropertyName == FlagPropertyName)
{
if (UBoolProperty *BoolProperty = Cast<UBoolProperty>(Property))
{
BoolProperty->SetPropertyValue((void*)object, value);
}
}
}
}
}
To test I added a bool Flag to ThirdPersonCharacter BP in ThirdPerson Template blueprint. Then I call my function, like so:
And this is what happens:
Access violation - code c0000005 (first/second chance not available)
UE4Editor_Engine!FActorEditorUtils::IsAPreviewOrInactiveActor() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\actoreditorutils.cpp:39]
UE4Editor_UnrealEd!FKismetDebugUtilities::OnScriptException() [d:\build\++ue4+release-4.15+compile\sync\engine\source\editor\unrealed\private\kismet2\kismetdebugutilities.cpp:131]
UE4Editor_UnrealEd!TBaseStaticDelegateInstance<void __cdecl(UObject const * __ptr64,FFrame const & __ptr64,FBlueprintExceptionInfo const & __ptr64)>::ExecuteIfSafe() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\public\delegates\delegateinstancesimpl.h:1027]
UE4Editor_CoreUObject!TBaseMulticastDelegate<void,UObject const * __ptr64,FFrame const & __ptr64,FBlueprintExceptionInfo const & __ptr64>::Broadcast() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\public\delegates\delegatesignatureimpl.inl:937]
UE4Editor_CoreUObject!FBlueprintCoreDelegates::ThrowScriptException() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:163]
UE4Editor_CoreUObject!UObject::execWireTracepoint() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:1601]
UE4Editor_CoreUObject!UObject::ProcessInternal() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:948]
UE4Editor_CoreUObject!UObject::CallFunction() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:845]
UE4Editor_CoreUObject!UObject::execVirtualFunction() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:2255]
UE4Editor_CoreUObject!UObject::ProcessInternal() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:948]
UE4Editor_CoreUObject!UFunction::Invoke() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\class.cpp:4525]
UE4Editor_CoreUObject!UObject::ProcessEvent() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\coreuobject\private\uobject\scriptcore.cpp:1318]
UE4Editor_Engine!AActor::ProcessEvent() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\actor.cpp:678]
UE4Editor_Engine!FInputActionHandlerDynamicSignature::Execute() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\classes\components\inputcomponent.h:108]
UE4Editor_Engine!FInputActionUnifiedDelegate::Execute() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\classes\components\inputcomponent.h:204]
UE4Editor_Engine!UPlayerInput::ProcessInputStack() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\userinterface\playerinput.cpp:1243]
UE4Editor_Engine!APlayerController::ProcessPlayerInput() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\playercontroller.cpp:2376]
UE4Editor_Engine!APlayerController::TickPlayerInput() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\playercontroller.cpp:4051]
UE4Editor_Engine!APlayerController::PlayerTick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\playercontroller.cpp:2039]
UE4Editor_Engine!APlayerController::TickActor() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\playercontroller.cpp:4133]
UE4Editor_Engine!FActorTickFunction::ExecuteTick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\actor.cpp:125]
UE4Editor_Engine!FTickFunctionTask::DoTask() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private icktaskmanager.cpp:269]
UE4Editor_Engine!TGraphTask<FTickFunctionTask>::ExecuteTask() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\public\async askgraphinterfaces.h:883]
UE4Editor_Core!FNamedTaskThread::ProcessTasksNamedThread() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\private\async askgraph.cpp:954]
UE4Editor_Core!FNamedTaskThread::ProcessTasksUntilQuit() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\private\async askgraph.cpp:701]
UE4Editor_Core!FTaskGraphImplementation::WaitUntilTasksComplete() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\core\private\async askgraph.cpp:1798]
UE4Editor_Engine!FTickTaskSequencer::ReleaseTickGroup() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private icktaskmanager.cpp:538]
UE4Editor_Engine!FTickTaskManager::RunTickGroup() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private icktaskmanager.cpp:1450]
UE4Editor_Engine!UWorld::RunTickGroup() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\leveltick.cpp:758]
UE4Editor_Engine!UWorld::Tick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\engine\private\leveltick.cpp:1373]
UE4Editor_UnrealEd!UEditorEngine::Tick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\editor\unrealed\private\editorengine.cpp:1630]
UE4Editor_UnrealEd!UUnrealEdEngine::Tick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\editor\unrealed\private\unrealedengine.cpp:391]
UE4Editor!FEngineLoop::Tick() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\launchengineloop.cpp:3025]
UE4Editor!GuardedMain() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\launch.cpp:166]
UE4Editor!GuardedMainWrapper() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:134]
UE4Editor!WinMain() [d:\build\++ue4+release-4.15+compile\sync\engine\source\runtime\launch\private\windows\launchwindows.cpp:210]
UE4Editor!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:264]
kernel32
ntdll
What am I doing wrong?
It crashes after the SetPropertyFlag returns, looks like there is some corrupted pointer. Personally, I find (void*)object cast suspicious, but I don’t know how to use it otherwise, I don’t know C++ and unreal libs well enough.
Anybody have any ideas?
scha
(scha)
February 2, 2017, 4:46pm
6
I finally found a way to make it work:
void UMyBlueprintFunctionLibrary::SetPropertyFlag(UObject* object, bool value)
{
static FName FlagPropertyName = TEXT("Flag");
if (UClass *cl = object->GetClass())
{
if (UProperty* Property = cl->FindPropertyByName(FlagPropertyName))
{
if (UBoolProperty *BoolProperty = Cast<UBoolProperty>(Property))
{
BoolProperty->SetPropertyValue(Property->ContainerPtrToValuePtr<float>(object), value);
}
}
}
}
The part with ContainerPtrToValuePtr is from ScriptBlueprintGeneratedClass.cpp, no idea why there is a <float> in there, but it seems to work.
1 Like
Thanks for posting your working code. I was suspecting the (void*) Object part was wrong but even though I looked through the engine source didn’t really figure out how it’s meant to be done. I guess the <float> confused me as much as it confused you. But with your working code I suspect this is just a small copy-paste error in ScriptBlueprintGeneratedClass.cpp and it really should just be <void> in both cases.
1 Like
scha
(scha)
February 2, 2017, 7:04pm
8
I’m confused with it too, I thought it should be <bool>.
But I just tested it, it compiles and works with all of them… probably it doesn’t matter. Only thing it changes is the ContainerPtrToValuePtr return type, which is immediately cast to void* by the SetPropertyValue.
1 Like