In this lesson, you will learn how to stabilize your framerate by managing object lifecycles through explicit reference types, preventing the Garbage Collector (GC) from triggering unnecessary and expensive cleanup passes.
The Problem: Why GC Stutters Occur
Unreal Engine uses an automated Garbage Collector to track UObject lifecycles. When objects are no longer "reachable" (meaning no UPROPERTY pointers point to them), the GC marks them for deletion. If your project creates and discards many objects, or maintains "leaky" references that keep stale objects alive, the GC must traverse the entire object graph to determine what can be safely removed. This traversal is a synchronous operation—it forces the game thread to pause, manifesting as a noticeable "hitch" or "stutter."
Managing References with UPROPERTY
The most effective way to help the GC is to be explicit. Any UObject pointer stored in a class header must be marked with UPROPERTY(). This informs the engine’s reflection system that the object is in use. If you omit UPROPERTY(), the GC has no idea the object is referenced, leading to crashes. Conversely, if you keep a UPROPERTY() reference to an object you no longer need, you create a memory leak that forces the GC to work harder during future passes.
Using TWeakObjectPtr for Non-Ownership
Sometimes you need to reference an actor or object, but you don't want to "own" it or force it to stay in memory. This is where TWeakObjectPtr shines. It allows you to track an object without preventing it from being garbage collected.
// In your header file
UPROPERTY()
AActor* OwnerActor; // Strong reference: Keeps the actor alive
TWeakObjectPtr<AActor> ObserverActor; // Weak reference: Safe, won't stop GC
When accessing a weak pointer, always check if it is still valid:
if (ObserverActor.IsValid())
{
ObserverActor->DoSomething();
}
By using TWeakObjectPtr, you prevent the object graph from becoming unnecessarily bloated, ensuring the GC has fewer objects to traverse. This reduces the time spent in the CollectGarbage routine, keeping your frame times consistent.
Key Takeaway: Use UPROPERTY() for mandatory ownership to keep objects alive, and TWeakObjectPtr for transient references to minimize the total object graph size and prevent GC-induced frame hitches.