Download

How to list UProperties of an UObject at runtime? Read/write UProperty?

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);

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;
		}
	}
}

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);
		}


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:

biOKZq1.png

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?

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.

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.

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.