One practical implication here is that you typically need to maintain a UPROPERTY reference to any Object you wish to keep alive, or store a pointer to it in a TArray or other Unreal Engine container class.
Q: Does TArray also need to add UPROPERTY?
Actors and their Components are frequently an exception to this.
Q: What’s the meaning of this? If another Actor or another ActorComponent is referenced in an Actor, can I not add UPROPERTY? Like this:
UCLASS()
class TEST_API AMyActor : public AActor
{
protected:
AOtherActor* TestActor;
};
I am dizzy. I know that UPROPERTY is generally required, but I don’t know when to use it and when not to use it when encountering Actor, ActorComponent and containers like TArray.
Help kid, please. It would be better if you could provide examples.
You should use UPROPERTY when hosting raw pointers to any other UObject (Actor/ActorComponent), so the garbage collector can see it.
This has two implications, 1) Garbage collector will null that pointer if the actor/object gets destroyed. Without it, the pointer will end up being garbage (pointing to memory that is not valid).
2) Stops the object being destroyed from the GC (UObject more than actors/actor components, will explain later).
So as you can read above, the UPROPERTY macro is crucial. Actors (and its owned components) are slightly different, but need to be addressed. Actors are held in a UPROPERTY array on the World Object, Actors will always get destroyed regardless if other objects are holding a raw UPROP pointer to it. This is cause the world sets the actor Pending Kill. The Actor will then set all its owned components pending kill.
The GC will clear up UObjects when no more “raw” pointers are holding it alive or its been marked pending kill.
So the take away here is, you should always use UPROPERTY above your Arrays or pointers. Keep a valid chain of reflection so the GC can transverse if you want the GC to know about those pointers (to clear them up (null them) ) or to keep that object alive (reference track).
If you want to just hold a pointer to something and don’t want to deal with GC/Reflection, then use TWeakObjectPtr. This will not affect the object’s lifetime at all and will return false from IsValid if pointer is null.
Thank you very much for your answer, I seem to get it.
The reason why Actor and ActorComponents are exceptions is that UPROPERTY for the raw pointers pointing to them is just for the garbage collector to set the pointer to nullptr, when they are destroyed.
UPROPERTY for the raw pointer pointing to UObject, it can additionally keep the pointed UObject active and avoid being recycled by the garbage collector.
Using UPROPERTY above the Unreal Engine container is equivalent to decorating every element in the container with UPROPERTY
Is my understanding correct? If there is something wrong, could you point it out, I would be very grateful.
I don’t think this is true. I’m not sure what “above the Unreal Engine container” means, but I’m pretty sure that there is no way to specify UPROPERTY for everything in a class.
Basically, always use it for your pointers to UObjects, and you probably want to use it for anything that is an Unreal container class (TArray, etc) and you must use it for anything that you want to expose to the editor.
That may be an overly simplified explanation, but it pretty much works for me. Anything that I want tunable by the editor, or that is a pointer to a game object, or contains pointers to game objects, gets a UPROPERTY.
OH! OK, yes, if you UPROPERTY() a container class, then it applies to what’s inside the container. I was thinking they meant you could UPROPERTY() a class definition and get it on all members. My bad!