Actor Pool Subsystem
- Base:
- UTickableWorldSubsystem
- Type:
- UNActorPoolSubsystem
- Header File:
- NexusActorPools/Public/NActorPoolSubsystem.h
A centralized management system that provides UWorld-specific access to AActor pooling functionality, acting as the primary interface for creating, managing, and accessing multiple FNActorPools.
What It Does​
- Unified Experience: Provides simple methods to get, spawn, and return
AActorwithout directly managing FNActorPoolss. - Centralized Pool Management: Automatically creates and maintains pool lifecycles for different
AActorsub-classes as requested. - Blueprint Accessible: Offers preferred Blueprint support for designers and non-programmers.
Usage​
Creating An Actor Pool​
When trying to maximize the usefulness of the actor pooling pattern, it is essential to try to create pools ahead of the actual usage of the AActors so that the initial creation cost is controlled.
Manually​
The time-tested, I know what I want, let me handle this approach. You can tell the UNActorPoolSubsystem to spin up pools via CreateActorPool().
- Blueprint
- C++
UNActorPoolSubsystem::Get(GetWorld())->CreateActorPool(MyActorClass, UNActorPoolsSettings::Get()->DefaultSettings);
Actor Pool Sets​
Utilizing UNActorPoolSets to define collections of FNActorPools that should be created when applied is a great way to develop reusable implementations across different levels and scenarios.
Automatically​
While not the best, it is the easiest way to create a FNActorPools for an AActor. Requesting an AActor from the UNActorPoolSubsystem without an existing FNActorPools for it will cause a new one to be created with the default settings.
Spawning An Actor​
The most common of interactions with the UNActorPoolSubsystem that you will have is asking it for an AActor. The API is as streamlined as possible.
If your Blueprint references the AActor class as a TSoftClassPtr rather than a hard reference, use Spawn Actor Async (or Get Actor Async if you don't need a transform) so the load and pool lookup happen off the calling frame.
- Blueprint
- C++
AMyActorType* SpawnedActor = UNActorPoolSubsystem::Get(GetWorld())->SpawnActor<AMyActorType>(MyActorClass, MyPosition, MyRotation);
Returning An Actor​
When you're finished with an AActor, you can interact with the UNActorPoolSubsystem and have it return the AActor to its designated FNActorPool. If the AActor implements the INActorPoolItem interface, you also have a more direct method call available, ReturnToActorPool().
- Blueprint
- C++
UNActorPoolSubsystem::Get(GetWorld())->ReturnActor(TargetActor);
Unknown Actor Behavior​
When ReturnActor is called with an AActor that does not belong to any pool managed by this subsystem, the ENActorPoolUnknownBehavior policy decides what happens:
| Value | Behavior |
|---|---|
Destroy | Destroy the unknown AActor. (default) |
CreateDefaultPool | Create a default pool on-the-fly for the AActor's class and return it there. |
Ignore | Do nothing; leave the AActor as-is. |
The initial value is read from Returned Unknown Actor on OnWorldBeginPlay. To override the policy at runtime — for example, to flip to Ignore while a streaming-out region tears down — call SetUnknownBehavior from native code. See the Native API section below.
UFunctions​
The methods exposed to Blueprint.
Get Actor​
/**
* Gets an actor from a given pool, creating a pool as necessary.
* @note This does not trigger any events on the given actor, it does not activate them in any way.
* @param ActorClass The class of the actor which you would like to get from the actor pool.
* @param ReturnedActor The returned actor, or nullptr if the pool could not provide one.
* @return true if an actor was successfully retrieved, false otherwise.
*/
bool GetActor(TSubclassOf<AActor> ActorClass, AActor*& ReturnedActor);
Check the bool return before reading ReturnedActor; it will be nullptr if the pool could not provide one (for example when capacity is exhausted and the pool is configured to refuse growth). When you need a fully positioned and activated AActor, use Spawn Actor instead.
This does not trigger any events on the given actor, it does not activate them in any way.
Spawn Actor​
/**
* Spawns an actor from a given pool, creating a pool as necessary, positioning it in the world and activating it.
* @note Unlike GetActor, this places the actor at the supplied transform and triggers OnSpawnedFromActorPool on the returned actor.
* @param ActorClass The class of the actor which you would like to spawn from the actor pool.
* @param Position The world position to spawn the actor at.
* @param Rotation The world rotation to apply to the spawned actor.
* @param SpawnedActor The spawned actor, or nullptr if the pool could not provide one.
* @return true if an actor was successfully spawned, false otherwise.
*/
bool SpawnActor(TSubclassOf<AActor> ActorClass, FVector Position, FRotator Rotation, AActor*& SpawnedActor);
Unlike Get Actor, SpawnActor places the AActor at the supplied Position / Rotation and triggers OnSpawnedFromActorPool on the returned AActor — use it whenever you want a fully activated AActor ready to play in the world. Check the bool return before reading SpawnedActor; it will be nullptr if the pool could not provide one (for example when capacity is exhausted and the pool is configured to refuse growth).
If you are working in native, use the native templated version of this function as it will let you pre-cast the return value to your desired type.
Return Actor​
/**
* Attempts to return an Actor to its owning pool.
* @note If the returned actor does not belong in a pool the UNActorPoolsSettings::UnknownBehavior is applied.
* @param Actor The target actor to return to a pool.
* @return true/false if the Actor was returned to a pool.
*/
bool ReturnActor(AActor* Actor);
Create Actor Pool​
/**
* Create an actor pool for the provided Actor class; if one does not already exist.
* @param ActorClass The class of the actor which you would like to create a pool for.
* @param Settings The settings to apply to the created pool.
* @return true/false if a new pool was created.
*/
bool CreateActorPool(TSubclassOf<AActor> ActorClass, FNActorPoolSettings Settings);
Has Actor Pool​
/**
* Does the given Actor class have a pool already created?
* @param ActorClass The class of the actor which you would like to check for a pool.
* @return true/false if a pool already exists.
*/
bool HasActorPool(const TSubclassOf<AActor>& ActorClass) const { return ActorPools.Contains(ActorClass); }
Apply ActorPoolSet​
/**
* Apply a preconfigured ActorPoolSet, creating the defined pools.
* @param ActorPoolSet The ActorPoolSet to evaluate.
*/
void ApplyActorPoolSet(UNActorPoolSet* ActorPoolSet);
Native API​
The methods below are available to C++ only — they are not exposed to Blueprint and are intended for native gameplay or systems code that needs direct access to the underlying FNActorPool instances or runtime policy controls.
Set Unknown Behavior​
/**
* Override the policy applied when ReturnActor is called with an Actor unknown to this subsystem.
* @note Initialized from UNActorPoolsSettings::UnknownBehavior on world begin play; use this to override at runtime.
* @param Behavior The new unknown-actor policy to apply.
*/
void SetUnknownBehavior(const ENActorPoolUnknownBehavior Behavior);
The starting value is sourced from Returned Unknown Actor when the world begins play. Call this to switch the policy mid-session — for example, to temporarily Ignore returns during a streaming teardown so transient AActors aren't recycled into pools that are about to be destroyed.
UNActorPoolSubsystem::Get(GetWorld())->SetUnknownBehavior(ENActorPoolUnknownBehavior::Ignore);
Get Actor Pool​
/**
* Get the pointer to the actor pool itself for a given Actor class.
* @param ActorClass The class of the actor which you would like to access a pool for.
* @return The pointer to the pool, or nullptr if it was not found.
*/
FNActorPool* GetActorPool(const TSubclassOf<AActor> ActorClass) const;
Returns nullptr when no pool exists for the supplied class — always null-check the result before dereferencing. Pair with Has Actor Pool when you only need a presence check.
Get All Pools​
/**
* Get an array of all the Actor Pools.
* @return An array of raw pointers to all the known FNActorPools
* @remark This is not meant to be used often and is more for debugging purposes.
*/
TArray<FNActorPool*> GetAllPools() const;
On Actor Pool Added​
/**
* Event triggered when a new pool is added to the UNActorPoolSubsystem.
* @remark Meant for native code only to ensure efficiency.
*/
OnActorPoolAddedDelegate OnActorPoolAdded;
A native multicast delegate (DECLARE_MULTICAST_DELEGATE_OneParam(..., FNActorPool*)) that fires whenever a new pool is registered — including pools created lazily by Get Actor, Spawn Actor, the CreateDefaultPool unknown-actor path, or an applied UNActorPoolSet. Bind from native via OnActorPoolAdded.AddUObject(...) and clean up with RemoveAll(this) in your teardown.