My game was getting random crashes that made no sense. Stack traces pointed to null pointers at lines in the code that were heavily checking for null pointers on everything. Things like if (MyPointer) MyPointer->DoStuff() were getting traced as source for exceptions. I couldn’t explain it.
Based on some tips in here, I started adding UPROPERTY() on… Everything… That I could, to prevent GC from doing silly stuff on its own. And it worked. All the crashes stopped.
I still don’t fully understand the GC and why doing that fixed the problems. But now I’m scared to leave anything not as an UPROPERTY and that causing some rare untraceable crashes. So I was wondering if there’s any significant downside to just blindly adding UPROPERTY to everything that can, just to be safe? Is there any reason why I shouldn’t?
UPROPERTY adds overhead in that the code gets bigger, and there is also some runtime overhead (although most of that is per-class, not per-class-instance, as far as I understand it.)
It also makes your class harder to configure in blueprints, because it will have tons of visible variables. If you don’t use blueprints, not so much of a problem. If you use blueprints, making then “Advanced Display” may help reduce clutter.
“I still don’t fully understand the GC and why doing that fixed the problems.”
Epic’s GC knows about UObjects. GC will only look at properties with UPROPERTY to see if the UOBJECT is being referenced. No UPROPERTY at all on an UOBJECT, then that UOBJECT can be deleted as it is not pointing to any other object and as that object is not being held as a reference by another UPROPERTY since you were not using any UPROPERTY.
Check out the sample projects from Epic and see where they use UPROPERTY(), then apply that to your game - really that’s the best advice we can give because it’s always entirely dependent on what you’re doing.
9/10 times though, UPROPERTY() is probably required when dealing with UObjects and members
Which brings me to a question: What is the correct boundary between UObject/UPROPERTY() versus TSharedPtr<> ?
I notice that UObjectBase does not in turn become a TSharedFromThis<>, so there’s some kind of hard boundary.
TSharedPtr is a simple smart pointer. (equivalent to native std::shared_ptr). It cannot be used with UObjects because the lifetime in this case is managed by GC.
UPROPERTY, in turn is used for reflection and generally allow UE4 to “see” that thing. (required for editor or blueprints).
Correct me someone if I’m wrong, but if you take care of a non-zero ref count to UObject(or derivative) and don’t need to expose this, then UPROPERTY isn’t neccessary.
I’m quite interested in understanding how to implement child components without using a UPROPERTY when possible because I like to take the “don’t pay for what you don’t use” approach as much as possible. I did a bit of research the past couple of days, and the part that I couldn’t find a solution for is how to make assets visible so that the project knows to package them. For example, I’m using a StaticMeshComponent, and I expect that the way the editor knows how to discover and package the mesh that it is using is by discovering it via the UPROPERTY referebce chains, but without using a UPROPERTY, I could not find a way to manually adjust what assets are packaged.
Anyone know the solution if there is one? Or know of an example in the source code I could reference?
The UPROPERTY Macro exposes the variable to Unreal Engines Reflection system through the Unreal Build Tool and Unreal Header Tool. The same with other macros such as UFUNCTION, USTRUCT, UCLASS etc. Without using these macros, you cannot use the variable/function/class etc in the editor, as the editor doesn’t recognize them.
Adding UPROPERTY() to a variable will expose that variable to the Reflection System, and the editor will be able to recognise it. You won’t however, be able to edit it in the editor. This is where **specifiers **and **meta data specifiers **come in.
These exposure macros are not to be confused with the Unreal Engine VM script classes such as FProperty, FFunction, FStrProperty etc.formally U, now F.
Using Unreal Engines Smart Pointer/Reference libraries ensures that the variables wrapped in a smart library, TSharedPtr for example, are automatically Garbage Collected when there are no more references to that variable. Not using the Smart Libraries with pointers for example, means you have to manually Garbage Collect your pointer variable.
I don’t think you can. Without the UPROPERTY macro, the Unreal Engine Build Tool won’t add the component to the reflection system, thus won’t be exposed in the editor.