How-To: Diagnose Pool Problems
Goal: answer the question every pooling system provokes - is pooling causing this? - in one command, then find out which of the usual causes it is.
Prerequisites
A pool in use and something misbehaving.
1. Rule pooling in or out
Crimson.ObjectPool.Bypass 1
Every acquire becomes a real SpawnActor and every release a real Destroy. Pooling is entirely out of the way.
| Result | Conclusion |
|---|---|
| Bug persists | Not a pooling bug. Stop looking here. |
| Bug disappears | A reuse bug. Go to step 2. |
Verify
With bypass on, gameplay should be identical apart from the actor churn. If behaviour changes in some other way, that difference is itself the clue.
2. Check the three reuse rules
A bug that disappears under bypass is almost always one of these. Full detail in Concept: The Reuse Contract.
| Symptom | Likely cause |
|---|---|
| Works the first time, wrong every time after | Per-use state initialised in BeginPlay, which runs once per actor lifetime. |
| Second use ends instantly | A one-way latch (bHasFired, bFinished) never reset on acquire. |
| Effects or damage happen two, three, four times over | A delegate bound in BeginPlay and rebound on every acquire. |
| Actor is visible but collides with nothing | The actor-level collision flag was cleared on release and never re-enabled. |
3. Read what the pools are doing
Crimson.ObjectPool.Dump
| Reading | Meaning |
|---|---|
created keeps rising during steady play | Instances are acquired and never released. The pool is a leak, not a pool. |
spawnsAvoided stays at 0 | Nothing is ever being recycled - same cause as above. |
highWater at or above capacity | Undersized. It is quietly spawning past its budget on every burst. |
live never returns to 0 when idle | Something is holding instances it should have released. |
Verify
Run the scenario, return to idle, and dump again. A healthy pool sits at
live=0 with pooled equal to its peak usage.4. Multiplayer symptoms
| Symptom | Likely cause |
|---|---|
| Clients lose the actor a few seconds after each release | Net dormancy disabled, or the actor is being moved far away on release. |
| Clients act on the previous use's data | COND_InitialOnly - it is never resent on a reused channel. |
| Rapid reuse is skipped on clients | Byte-identical activation state. Add a monotonic counter. |
Warning: refused on a client | Client code is calling acquire or release. Both are server-only for replicated classes. |
All four are covered in How-To: Pool a Replicated Actor.
See also
- Concept: The Reuse Contract
- How-To: Pool a Replicated Actor
- How-To: Size and Prewarm a Pool