I’m working on a bullet hell project that uses an object pool BP to spawn, recycle and destroy projectile actors as needed. Characters in the game call the pool via an interface with a soft object class reference input. When the pool needs to spawn a specific projectile class for the first time, the pool BP takes care of loading the class via async load. When a given projectile class no longer has a “customer” character, the pool destroys all projectiles of that class.
Given the pool persists throughout the game, will the unused projectile classes (all associated actors destroyed by the pool BP) get automatically unloaded?
If you have a UPROPERTY to a uobject (class, actor, component, widget etc etc) which is not soft, then you are keeping it from being garbage collected. In unreal hard pointers to UObject are automatically nulled when an object is destroyed. It should all be handled magically by the GC.
Memory Management & Garbage Collection in Unreal Engine 5 | Mikelis' Game Blog
Garbage Collection & Dynamic Memory Allocation - Old UE4 Wiki
All about Soft and Weak pointers | Tutorial
1 Like
Thank you – very helpful. I haven’t explicitly added a UPROPERTY reference to any of the projectile classes, so it sounds like garbage collection should happen once all instances are destroyed.
1 Like
Keep in mind for pointers to UObject types that you must store them under UPROPERTY to prevent them from being garbage collected while they are still in use. If not the garbage collector is going to run over them regardless.
The normal process is:
- Have a soft pointer on a UPROPERTY.
- Load the data from the soft ptr on demand, or store the loaded instance under UPROPERTY.
- When done with the instance, destroy it.
- pointers to destroyed UObject are automatically nulled.
- Unreferenced data is collected.
Unreferenced means “not in UPROPERTY, not in scope”, so if you were to store an instance on a class property not marked UPROPERTY the GC will collect it too soon. You can think of the referencing process as one large tree from base to branches. Everything is referenced by something else, and if it’s not the branch falls off and is collected as garbage. UPROPERTY is used to build the references, the GC just runs every so many seconds to check what fell off.
It’s probably easiest to just load things on demand from the soft ptr in some function when you need it. The thing with storing hard pointers under UPROPERTY is that the classes just don’t get unloaded. People often run into this when they realize their class is recursively loading a ton of other classes into memory before changing pointers to soft. Say, datatables not using soft ptrs for example. massive memory waste, everything loads right away and often never unloads.