C++ Dynamically add UPROPERTY

Did you actully check why it crashes when you add UPROPERTY()? check logs in Saved/Log

UProperty can be dynamically created, if bluepritns can do it why not you can do it? You are aware that each object in reflection system has it’s represenative object? You definitly frequintly use UClass*, the same thing is with UProperty()
https://docs.unrealengine.com/latest/INT/API/Runtime/CoreUObject/UObject/UProperty/index.html

Note that UPROPERTY() is just dummy macro for UHT to generate some extra code that generates those UProperty objects, you can check it here, but from look of it it’s also dedicated for constructor use only:
Intermediate\Build*****\Inc\ModuleName\ModuleName.Generated.cpp

But doing this dynamiclly can be even more messy hack, maybe lest try to figure if we can get work without doing that. What you actully trying to do add component in design time?

Sorry I could not find a suggestion-section to post in + this is kinda hard to explain.

In UE4 as we all know we can not spawn actors at designtime. And spawning stuff at designtime outside of the actor’s constructor can be a real pain, but is possible. But on top of that we can not mark those as UPROPERTY.

Example:

I have an actor with an array of shapecomponents so that I can use the same door with different triggerboxes without having to create a new c++/blueprint class for each door.

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyDynamicTriggers")
TArray<UShapeComponent*> Triggers;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyDynamicTriggers")
TArray<FMyTriggerSetup> TriggersSetup; // Contains an enum telling the actor what type of shapecomponent to spawn

// outside of the constructor in the PostEditChangeProperty():
void FooClass::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
	Super::PostEditChangeProperty(PropertyChangedEvent);
	if (PropertyChangedEvent.MemberProperty->GetName() != "Triggers")
    {
     ...
    case ECollisionShapeEnum::Capsule:
       Triggers[i].ShapeComp = NewObject<UCapsuleComponent>(this); // Note: NO FName param or UE4 will go nuts (duplicate names) :P.
    break;
     ...
     }
}

The above seems to work at first. But when you try to edit the Capsule component size, location, etc. you can’t… It’s readonly and you get the message:

92642-bp.png

Okay… And there is no way to do this dynamically in c++. But it is possible in blueprints (blueprints do this regardless of whether you want it or not).

Because I really do not want to use blueprints just for this one variable, I came up with an ugly hack (but still the best one out there I think). It basically puts the ShapeComponent (which we can not mark as UPROPERTY in c++) inside a struct and then we mark the variable of that struct as a UPROPERTY:

USTRUCT(BlueprintType)
struct FShapeCompHack
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ShapeCompHack")
	UShapeComponent* ShapeComp;

	FShapeCompHack()
	{
		ShapeComp = nullptr;
	}
};

And then in the header:

	UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "BaseCrusher")
	TArray<FShapeCompHack> Triggers; //TArray<UShapeComponent*> Triggers; // Apply dirty hack because... you know...

I can, to some degree, understand that actorspawning at designtime is problematic. But not being able to mark dynamically-spawned components in c++ as a UPROPERTY seems like a really bad limitation and I see not reason why this was done. I already have to go to lengths to spawn stuff dynamically at designtime. This just makes it so much more worse.

Also there may be a bug with this particular hack where spawning stuff dynamically and then running the PostEditChangeProperty() function will cause the “Multiple values selected” to appear on ALL fields every time. It seems that the editor selected all components in the array (even though the editor says it selected only one). But I also have a workaround for that in place… The (possible) bug is kinda hard to explain but then again, I’m applying a workaround (multiple values) on top of a hack (no dynamic uproperty) on top of a workaround (no actor spawning at designtime) to get around the engine limitations. And then there is that intended behavior where only the triggerbox that is the root-component can overlap/hit non-pawns. So if you try to apply all this for a dynamic array of trigger-shapes that must collide with something other than pawns, then not even this will work for you…

See also:

TLDR version: What I’m trying to do is to spawn components dynamically at design-time outside of the actor’s constructor, in an TArray (because I don’t know how many I may need), have it/it’s properties exposed in the editor and implement it in c++. All of this is easily possible except for “have it/it’s properties exposed in the editor”.

It does not actually crash, I actually got it to work, it’s messy but it works. But the final behavior of this implementation feels slightly buggy regarding Editor behavior. But that is somewhat expected because I’m doing stuff that I’m not supposed to. I’m basically editing a read-only property in the editor.

I agree that if blueprints can do it, we must be able to do it as well, somehow. But so far nobody knows how and the way of doing it likely involves more ‘hacking around’. Everywhere I search/ask I get the same answer so far “not possible / use hacks”.

Yes I’m aware that UPROPERTY is a macro (ObjectBase.h) but it’s real implementation seems to go deeper into the internal code (UE4 Header Tool I believe).

(I hit the comment-character-limit, so making 2nd comment)

The reason for spawning dynamic components at runtime is to make classes even more generic. Let’s say I have a moving-platform that automatically starts moving when a character enters it’s triggerbox. That moving platform can have an unlimited number of shapes but it’s behavior is always the same.

The current way of implementing the above example would be to either have a huge enum with all the possible shapes and then change the StaticMesh&UShapeComponent depending on the enum in the constructor. This however is quite messy and not very friendly. Another solution would be to create a child-class for each platform (not viable if you have ~500 variations).

Another solution (my preferred solution and what I’m using now) is to instead have an array of components that are exposed to the editor. Then in the editor I put down the platform somewhere, I set it’s static mesh and then I click on the plus-sign to add a new component to the UShapeComponent-TArray and add new triggershape(s) and position and resize them the way I want them. However this last part either requires dynamic UPROPERTIES or a lot of ‘workarounds’ or blueprints. But I’m trying to avoid using blueprints as much as possible. C++ is more stable, gives me more control, is easier to debug, does not require me to jump through loops when working with statics, does not have it’s pins broken when a baseclass changes (hard to track down all the broken pins), is often shorter/faster to code, etc.

It kind of sound like you over complicating things, why you want even more generic actor? for prosidual generation? or for user selection?

If for selection i think you really over complicating things, you throwing away selection tool that engine already have… which is Content Browser, actors diffrent setups should be subclasses even if it’s just one varable changed, thats how all Unreal games deal with it

Yes I’m aware that UPROPERTY is a
macro (ObjectBase.h) but it’s real
implementation seems to go deeper into
the internal code (UE4 Header Tool I
believe).

As i said it’s a dummy macro, it’s empty and ignored and UHT (whcih you call UE4 Header Tool) generates code which register uproperties to reflection system, it’s C++ code, but if you look at it is still static. You can look it up i point you to it, it uses same API

That’s how we always did it in Unity and some other engines. This prevents us from having to create hundreds, if not thousands of sub-classes just to change 1 parameter. Even though the solution below is pretty good and works 100% fine, I personally still prefer the way we did it in the other engines.

However, (in this specific case) it seems you are right. After some more trial&error I came up with a very simple solution to the problem. It’s so simply you will probably ask me why I didn’t do that in the first place. But neither I nor anybody I asked including one experienced guy I paid to find a better solution could find this simple solution.

Solution:
Add a USceneComponent to the object which will act as the parent-container. Then in the editor at designtime add any collisionshape (box/sphere/capsule) to that actor and make it a child-component of the parent-container. Then have some code bind them in BeginPlay():

	TArray<USceneComponent*> ChildComponents;
	TriggerParentComp->GetChildrenComponents(true, ChildComponents);
	for (USceneComponent* ChildComponent : ChildComponents)
	{
		UShapeComponent* TriggerComp = Cast<UShapeComponent>(ChildComponent);
		if (TriggerComp != nullptr)
		{
			Triggers.Add(TriggerComp);
			TriggerComp->OnComponentBeginOverlap.AddDynamic(this, &FooClass::TriggerOnBeginOverlap);
		}
		else
		{
			LOG_ERROR("Only UShapeComponent's are allowed to be added as child-components to the TriggerParentComp.")
		}
	}

And that’s it. It works because the trigger-shape is added through the editor and is thus automatically marked as UPROPERTY. Now I can use 1 single c++ class and still have an unlimited amount of customizable trigger-shape-components for it without having to subclass it.

But for procedural generation and other more complex cases it may still be handy to be able to tell the engine to mark it as a UPROPERTY. I still would love to know how to properly mark a “designtime c++ generated component” as UPROPERTY.

1 Like