Garbage Collection Overview
Unreal's game-level memory management system uses reflection to implement garbage collection.
Overview
Unreals game-level memory management system uses reflection to implement garbage collection. Working effectively in Unreal requires some understanding of how these two systems interact.
What is reflection?
Inform yourself about Unreals (Reflection) Property System and how to use it. Reflection allows the engine to determine if objects are still referenced by other objects, making garbage collection a viable strategy for managing memory.
Garbage Collection
One of the most important tasks within a game engine is managing memory. Unreals approach to solve this problem is the usage of garbage collection. In this approach, the engine will automatically delete objects when they are no longer needed. An object is no longer needed when it is no longer referenced by any other object. If you are more curious about Garbage Collection, visit garbage collection–computer science.
Unreal uses the reflection system to drive garbage collection. Because the engine knows about your objects and properties, it can recognize when an object is no longer needed and automatically delete it.
While this automatic memory management does significantly reduce the mental workload to working in the engine, it is important to understand at a high level how it works, as it can only work well when you follow the rules.
Some exceptions to the rules are always there, be sure to know what you are doing if you break the rules!
-
Every member of a class should be declared as a UPROPERTY
If an member is left “naked,” unreal will not know about it. So, an object you are pointing at could get deleted out from under you! It is safe to leave value types such as an int or a bool “naked” although they could not be saved, replicated, or appear in the editor.
-
Member pointers should only point at UObject or UObject-derived objects
The garbage collector is only smart enough to recognize relationships to an object, so the object could get deleted out from under your pointer.
-
Any non-UObject pointer must be pointing to something “global” in the engine, or something within its own UObject
The garbage collector could delete the object that owns what you are pointing at.
-
The only container that is safe to have UObject or UObject-derived pointers in is a TArray
UObject-derived pointers & objects would be any object, component, or actor.
Remember, the garbage collector relies on reflection data!
Structs vs. Objects
Structures are intended for use as "value" types. They are best suited for small amounts of data to be reused in objects and actors. For example, FVector, FRotator, FQuat. They are not deleted, so they must always exist within a UObject.
One advantage of UStructs is that they are very small. While a UObject must contain accounting data in addition to your data, UStructs (technically UScriptStructs) are only as large as the data you store in them. The garbage collector doesn't have to do as much work to manage them.
However, UStructs do have their limitations. A direct reference to the member structure of another object is not safe.
UObjects are collected by the garbage collector. Although they are heavier, it is generally safe to point to them. Keep in mind that each UObject is another thing for the garbage collector to keep track of. Although the engine can easily handle thousands of objects, this capability should be used carefully. If your project requires thousands of instances of something and UStructs are acceptable, they will generally be more powerful than UObjects.
Containers
For the garbage collector to do its work of determining what is safe to delete, it must traverse every field of every object. While Unreal provides several types of containers (TArray, TMap, …) the garbage collector only considers pointers in TArray.
See Also
Some more specifics and code examples related to memory management, see Dynamic Memory Allocation.