CrimsonObjectPoolComing to FabFree
Get early access on Discord

Recycle actors instead of spawning and destroying them — with an explicit acquire/release API and a documented path for replicated actors.

Free · Performance · Unreal Engine 5

Spawn it once. Reuse it all match.

Projectiles, impact effects, pickups, shell casings and summoned turrets pay for a full SpawnActor and Destroy every single time. CrimsonObjectPool replaces that with a per-world subsystem that recycles actors by class — Acquire Actor hands you a live instance, Release Actor parks it, and the next acquire reuses it. Replicated actors included.

Video coming soon

Why CrimsonObjectPool

Pooling that stays predictable — explicit at every call site, correct over the network, and removable in one command.

Explicit, never implicit

The plugin never hooks engine spawn paths. An actor is pooled only where you asked for it to be, so there is no hidden behaviour to reason about when something goes wrong — and nothing changes for the rest of your project.

Replicated actors, done right

Parked actors go dormant rather than being hidden away at a far-off location — because a hidden, non-colliding or net-culled actor loses relevancy, and that makes every client destroy its copy, which is exactly the cost the pool exists to remove.

Bulk spawns without the hitch

Queue acquires and the pool serves them across frames under a MaxSpawnsPerFrame budget. Requests a warm pool can fill from its free list skip the budget entirely — only real spawns are throttled.

Sizing you control per class

Set capacity, growth policy (Grow or HardCap) and prewarm counts globally or per actor class. Class-override lookup walks up the hierarchy, so one entry can cover a whole family of projectiles.

Counters that prove it works

Crimson.ObjectPool.Dump prints pooled, live, high-water, created and spawns-avoided per class. If created keeps climbing, instances aren't being released — and you can see it in one command.

Rule pooling out instantly

Crimson.ObjectPool.Bypass 1 turns every acquire into a real SpawnActor and every release into a real Destroy. Reproduce a bug with pooling off and you know immediately whether the pool is involved.

A closer look

Two node swaps and you're pooling

Replace Spawn Actor from Class with Acquire Actor, and Destroy Actor with Release Actor. That's the whole integration for a cosmetic actor — no interface, no subclass, no settings changes. You cannot tell whether an acquire recycled or spawned, and you don't need to.

Video coming soon

The reuse contract

A pooled actor is never destroyed, so BeginPlay runs once per lifetime, not once per use. One-way latches stay latched and per-use delegate bindings multiply. Implement the optional ICrimsonPoolable hooks to control reactivation yourself — it ships in CrimsonCommon, so any plugin's actor can be pooled with no glue code.

Video coming soon

The trap that reaches production

COND_InitialOnly sends a property only in an actor's first bunch. A recycled actor's channel is already open on its second use, so the condition is skipped, the property is never resent, and clients keep acting on the first use's data. Nothing errors and nothing logs — which is why the docs call it out before you write the code.

Video coming soon

Technical details

Engine
UE 5.8
Platforms
Windows, Mac, Linux
Blueprint-ready
Yes
C++ required
No
Network replicated
Yes
Dependencies
CrimsonCommon, DeveloperSettings, NetCore
Last updated
July 2026

Frequently asked questions

Do I need C++ to use it?
No. Acquire, release, deferred and queued acquires, prewarm, drain and every stat are Blueprint-accessible. Only GetPoolReleaseDelegate — an optional way for an actor to reclaim itself — is C++-only, because a Blueprint cannot hand out a delegate reference. Blueprints call Release Actor instead.
Does it work in multiplayer?
Yes, and it's fully supported — but pooling a replicated actor has rules, because replication is built around actors being created and destroyed and a pooled actor is neither. Acquire and release are server-only for replicating classes, net dormancy stays on while parked, and a monotonic counter in your activation state keeps two consecutive uses from looking byte-identical. Read How-To: Pool a Replicated Actor before you write the code.
Do I have to implement an interface?
No — it's optional. Without it the pool handles reactivation for you. Implementing ICrimsonPoolable makes your OnAcquiredFromPool the only reactivation that happens, which is what you want when an actor needs to reset its own state.
Does it depend on other Crimson plugins?
Only CrimsonCommon, per the suite's Cardinal Rule — for the log macros and the ICrimsonPoolable contract. The interface lives there rather than here so that actors in other Crimson plugins can be pooled with no glue code, which is exactly how ACrimsonProjectile works.
Is it really free?
Yes. It's part of the free foundation tier, alongside CrimsonCommon and the other utility plugins.

Stop paying for spawns you already paid for

Swap two nodes, watch spawnsAvoided climb, and keep the bypass switch in your pocket for the day something looks wrong. The Quick Start pools a cosmetic actor end to end in about five minutes.