Does the UPROPERTY macro have any benefit for things that don't need it?

I’ve heard vaguely that things declared to be UPROPERTY can be handled by the engine’s garbage collector, but I’m having trouble understanding the practical application.

If I have a variable that is only used on the C++ side, do I gain anything from making it a UPROPERTY? Does the answer change if it’s a pointer?

Yep, aside the fact that UPROPERTIES has a lot of configs for your variables including network capabilities, also special functionality between your classes and the editor, some pointers lives forever if you don’t take care in your code, making those UPROPERTIES is a easy way to handle that. You might take a look of the documentation, there is a lot of stuff you can do with metadata Properties | Unreal Engine Documentation

1 cool example I have in mind right now:

UPROPERTY(EditAnywhere, Category = “IDS”, Meta = (InlineEditConditionToggle, MakeEditWidget = true))
uint32 bOverrideLightMapRes : 1;

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Lighting, meta = (ClampMax = 4096, EditCondition = “bOverrideLightMapRes”))
int32 OverriddenLightMapRes = 64;

I did this when I created a new static mesh component, and I wanted to override the light map resolution, this allow me modify my int based on my bool, like a toogle, there is a lot of examples like this, UPROPERTIES are very useful

EDIT: here the metadata for uproperties UM:: | Unreal Engine Documentation

1 Like

That’s cool, I didn’t know about the metadata. What if you don’t need any of that, though? Say the variable is just used C+±side, isn’t doing anything fancy, and isn’t a pointer. Do I gain anything then? Do I lose anything by making it a UPROPERTY, increased compile time perhaps?

UHT will generate a bit more code (insignificant increase in executable size) and that will translate to a very slight increase in runtime memory allocation for the associated entry in the reflection data structures (again, insignificant).

The main thing to be aware of is that if you make something UPROPERTY() without any specifiers, then it will default to being serialized. So if the property is on an actor or asset class, you’re adding a bit of processing time and storage space usage. It would rarely make sense for something to be serialized if not editable though anyway.

Anyway, if there’s no reflection functionality you need, then just don’t make it a UPROPERTY. There’s nothing wrong with using non-reflected variables.

Awesome info, another question.

I have a class that’s spawned in a level blueprint and outer’d to that level. Inside that class is a UDataTable*. When the level is switched my class will be destroyed, but does the UDataTable* need to be reflected in order for the DataTable it’s pointing to, to be garbage collected? This question also extends to pointers to things created with NewObject, do they need to be reflected for garbage collection to work?

Edit: May have answered my own question. This wiki page says that you need at least one pointer that is a UPROPERTY to be pointing to something created with NewObject for it to not be garbage collected. Would a good heuristic be, “If I care about using something created with NewObject through a pointer, I should make that pointer a UPROPERTY to make sure it doesn’t get garbage collected”?

Member variable pointers to UObjects should pretty much never be raw, since you can end up with a dangling pointer. They should generally always be marked UPROPERTY and/or use TWeakObjectPtr if you specifically don’t want that property to keep the object loaded.

Your last statement is essentially correct, garbage collection will happen by default; you use UPROPERTY to prevent it; not enable it. But there is nothing special about objects you yourself create with NewObject, all UObjects are treated the same way.