Game Development Object Pool
Use this skill when repeated creation and destruction of short-lived objects is causing measurable hot-path churn and the real question is whether reuse infrastructure is justified, bounded, and safe.
This skill is for reviewing or designing pooling boundaries without turning pooling into a default architecture. Its job is to prove the hot path exists, define a safe reset contract, choose the smallest ownership boundary, and return a practical implementation and verification brief another agent can apply incrementally.
If the engine is unspecified, keep the recommendation engine-agnostic first. Do not assume Godot Node lifecycle, Unity GameObject pooling, or ECS-specific reuse patterns until the target runtime is explicit.
For engine-facing lifecycle, signal, timer, and resource-sharing details, see references/godot-reference.md.
Purpose
This skill is used to:
- determine whether pooling is justified at all
- identify which object types are worth pooling and which are not
- define ownership boundary, API, exhaustion behavior, and reset rules explicitly
- keep engine lifecycle hazards visible instead of hidden inside reuse infrastructure
- return a concrete rollout and benchmark plan
Use this skill when
Use this skill when you see one or more of these signals:
- frequent spawn/despawn cycles for short-lived objects
- GC spikes or allocation churn during gameplay
- frame drops when many identical objects appear at once
- systems such as bullets, hit VFX, floating damage numbers, enemy spawn waves, or recycled UI rows/cards
- repeated
Instantiate / QueueFree style churn in a hot path
- the user explicitly mentions optimization, too many instantiate/destroy calls, lag when spawning, GC spikes, or pooling
Trigger examples
- "We get frame drops when many bullets spawn at once"
- "Should these floating damage numbers use pooling?"
- "This VFX spam causes GC spikes during combat"
- "Please review whether pooling is actually justified here"
Do not use this skill when
Do not use this skill when:
- object count is small or infrequent
- the object has complex external state that is expensive or unsafe to reset
- profiling shows no meaningful CPU, allocation, or GC problem
- the lifecycle is too irregular to estimate capacity sanely
- engine-native reuse already solves the problem
- pooling would create a global mutable dependency for unrelated systems
Pattern
- Primary pattern: Tool Wrapper
- Secondary pattern: Generator
Related skills and routing notes
- Start here only after there is measured churn; if the real issue is scene or subsystem ownership of reused objects, pair early with
game-development-coordinator.
- Pair with
game-development-entity-reference-boundary when pooled reuse makes direct references, IDs, handles, or delayed callbacks unsafe across object lifetimes.
- Pair with
game-development-state-change-notification when acquisition and release should invalidate caches, refresh observers, or suppress stale UI/gameplay listeners.
- Pair with
game-development-time-source-and-tick-policy when pooled objects carry timers, cooldown windows, delayed release, or cadence-sensitive reset logic.
- Hand off to
game-development-command-flow when pooled objects are only one piece of a larger queued action or spawn-dispatch surface.
- Hand off to engine-specific lifecycle references once the pool boundary is justified and the remaining risk is runtime lifecycle correctness rather than pooling fit.
Diagnostic checklist
| Question |
Good sign for pooling |
Warning sign |
| Creation frequency |
High and repeated |
Rare or incidental |
| Lifetime |
Short and bounded |
Long-lived or highly variable |
| Reset complexity |
Small and deterministic |
Order-sensitive or leaky |
| Capacity estimate |
Reasonably predictable |
Unknown or wildly unstable |
| Profiling evidence |
Clear hot-path churn |
No measurable bottleneck |
Decision rules
Prefer pooling when
- reuse is frequent
- allocation/free cost is visible in profiling
- object behavior is standardized enough to reset safely
- pool size can be estimated or capped
- the hot path is local to a scene or subsystem
Avoid or limit pooling when
- usage is too sparse to justify complexity
- object state crosses too many boundaries
- reset logic is more error-prone than the original allocation cost
- pooling would hide design problems instead of fixing them
Partial strategy
Pool only the hot-path objects first.
Do not globalize pooling prematurely. Prefer the smallest ownership boundary that matches the reuse pattern:
- scene-local
- system-local
- shared service only when clearly justified
Before recommending pooling, also consider whether the simpler answer is:
- reducing spawn frequency
- batching or effect consolidation
- using engine-native virtualization or reuse already present
- caching plain data while leaving object lifecycles alone
Workflow
Confirm the symptom with profiling or a reproducible hot path.
- Capture baseline frame time
- Note spike frequency
- Check allocation / GC evidence
- Record peak concurrent active object count
Identify candidate object types.
- short-lived reusable
- long-lived but stable
- not worth pooling
Define pool boundary.
- per scene
- per gameplay system
- shared service only if multiple consumers truly need the same lifecycle rules
Define the pool API.
Typical surface:
Get()
Release()
Prewarm(count)
- exhaustion policy (
expand, fallback instantiate, or drop request)
Define lifecycle hooks.
OnAcquire
OnRelease
ResetState
Write the reset contract before implementation.
Review at minimum:
- transform / position / rotation / scale
- visibility and z-order
- velocity / movement state
- timers / tweens / animation state
- collision and hitbox state
- text / UI content
- signal or event subscriptions
- async / cancellation state
- parent attachment / process mode / layer or canvas state
Integrate with the target engine safely.
- identify which object lifecycle rules are engine-native and which are app-owned
- prefer explicit activation/deactivation over magical hidden reuse
- avoid duplicate event or signal connections on reuse
- keep world-space and UI-space lifecycles separate
- if the task is Godot-specific, use
references/godot-reference.md for scene-tree and signal details
Add safety checks.
- double-release guard
- missing-release detection
- pool exhaustion behavior
- debug counters or structured logging where helpful
Re-profile with the same scenario.
Keep the pool only if the gain is measurable and the lifecycle remains understandable.
Output contract
Return the result using assets/object-pool-brief.md in this section order.
When using this skill, return these sections:
- Candidate analysis
- Pool design
- Reset contract
- Engine integration notes
- Migration steps
- Benchmark plan
Engine-specific notes
Godot / .NET
Node lifecycle safety matters more than clever pooling.
- Reused nodes can leak state through:
- signals
- child nodes
- tweens
- animation state
- stale parent attachment
- pending async callbacks
- For UI recycling, verify:
- text
- focus
- bindings
- visibility
- layout assumptions
- For gameplay recycling, verify:
- transform
- collision
- process state
- timers
- callbacks
- If pooling removes GC spikes but makes behavior nondeterministic, the design is not done yet.
- Use
references/godot-reference.md when you need concrete guidance on _Ready() vs _EnterTree(), RequestReady(), release strategies, async ghost callbacks, or shared-resource contamination.
If the target runtime is not Godot/.NET, translate these notes into the equivalent lifecycle and ownership model instead of copying Node-specific advice verbatim.
Common pitfalls
- pooling everything blindly
- adding a global pool before identifying a hot path
- missing one reset responsibility and leaking state across uses
- allowing unbounded growth with no visibility
- mixing unrelated lifecycles in one pool
- keeping pooling after measurements show no material win
Companion files
assets/object-pool-brief.md — reusable output template for returning the pooling implementation or review artifact
references/godot-reference.md — Godot-specific lifecycle, signal, timer, async, and resource-sharing cautions for pooled nodes
Validation
A good result should satisfy all of the following:
- simpler non-pooling alternatives were considered first
- pooling candidates were justified by evidence, not instinct
- reset rules and ownership boundaries are explicit enough to review
- exhaustion behavior is defined
- before/after verification is included
- the proposed pooling keeps the codebase understandable
Completion rule
This skill is complete when the agent has:
- decided whether pooling is justified at all
- identified what should and should not be pooled
- defined the ownership boundary, API, exhaustion behavior, and reset contract
- described engine lifecycle and integration risks clearly
- returned a concrete migration and benchmark plan
1---2name: game-development-object-pool3description: Use when a cross-engine gameplay task needs a Layer 2 shared-runtime performance review for spawn/despawn churn, GC spikes, or short-lived reusable objects, and the agent must decide whether pooling is truly justified before introducing reuse infrastructure.4---56# Game Development Object Pool78Use this skill when repeated creation and destruction of short-lived objects is causing measurable hot-path churn and the real question is whether reuse infrastructure is justified, bounded, and safe.910This skill is for reviewing or designing pooling boundaries without turning pooling into a default architecture. Its job is to prove the hot path exists, define a safe reset contract, choose the smallest ownership boundary, and return a practical implementation and verification brief another agent can apply incrementally.1112If the engine is unspecified, keep the recommendation engine-agnostic first. Do not assume Godot `Node` lifecycle, Unity `GameObject` pooling, or ECS-specific reuse patterns until the target runtime is explicit.1314For engine-facing lifecycle, signal, timer, and resource-sharing details, see `references/godot-reference.md`.1516## Purpose1718This skill is used to:1920- determine whether pooling is justified at all21- identify which object types are worth pooling and which are not22- define ownership boundary, API, exhaustion behavior, and reset rules explicitly23- keep engine lifecycle hazards visible instead of hidden inside reuse infrastructure24- return a concrete rollout and benchmark plan2526## Use this skill when2728Use this skill when you see one or more of these signals:2930- frequent spawn/despawn cycles for short-lived objects31- GC spikes or allocation churn during gameplay32- frame drops when many identical objects appear at once33- systems such as bullets, hit VFX, floating damage numbers, enemy spawn waves, or recycled UI rows/cards34- repeated `Instantiate` / `QueueFree` style churn in a hot path35- the user explicitly mentions optimization, too many instantiate/destroy calls, lag when spawning, GC spikes, or pooling3637### Trigger examples3839- "We get frame drops when many bullets spawn at once"40- "Should these floating damage numbers use pooling?"41- "This VFX spam causes GC spikes during combat"42- "Please review whether pooling is actually justified here"4344## Do not use this skill when4546Do not use this skill when:4748- object count is small or infrequent49- the object has complex external state that is expensive or unsafe to reset50- profiling shows no meaningful CPU, allocation, or GC problem51- the lifecycle is too irregular to estimate capacity sanely52- engine-native reuse already solves the problem53- pooling would create a global mutable dependency for unrelated systems5455## Pattern5657- Primary pattern: **Tool Wrapper**58- Secondary pattern: **Generator**5960## Related skills and routing notes6162- Start here only after there is measured churn; if the real issue is scene or subsystem ownership of reused objects, pair early with `game-development-coordinator`.63- Pair with `game-development-entity-reference-boundary` when pooled reuse makes direct references, IDs, handles, or delayed callbacks unsafe across object lifetimes.64- Pair with `game-development-state-change-notification` when acquisition and release should invalidate caches, refresh observers, or suppress stale UI/gameplay listeners.65- Pair with `game-development-time-source-and-tick-policy` when pooled objects carry timers, cooldown windows, delayed release, or cadence-sensitive reset logic.66- Hand off to `game-development-command-flow` when pooled objects are only one piece of a larger queued action or spawn-dispatch surface.67- Hand off to engine-specific lifecycle references once the pool boundary is justified and the remaining risk is runtime lifecycle correctness rather than pooling fit.6869## Diagnostic checklist7071| Question | Good sign for pooling | Warning sign |72|---|---|---|73| Creation frequency | High and repeated | Rare or incidental |74| Lifetime | Short and bounded | Long-lived or highly variable |75| Reset complexity | Small and deterministic | Order-sensitive or leaky |76| Capacity estimate | Reasonably predictable | Unknown or wildly unstable |77| Profiling evidence | Clear hot-path churn | No measurable bottleneck |7879## Decision rules8081### Prefer pooling when8283- reuse is frequent84- allocation/free cost is visible in profiling85- object behavior is standardized enough to reset safely86- pool size can be estimated or capped87- the hot path is local to a scene or subsystem8889### Avoid or limit pooling when9091- usage is too sparse to justify complexity92- object state crosses too many boundaries93- reset logic is more error-prone than the original allocation cost94- pooling would hide design problems instead of fixing them9596### Partial strategy9798Pool only the hot-path objects first.99100Do not globalize pooling prematurely. Prefer the smallest ownership boundary that matches the reuse pattern:101102- scene-local103- system-local104- shared service only when clearly justified105106Before recommending pooling, also consider whether the simpler answer is:107108- reducing spawn frequency109- batching or effect consolidation110- using engine-native virtualization or reuse already present111- caching plain data while leaving object lifecycles alone112113## Workflow1141151. Confirm the symptom with profiling or a reproducible hot path.116 - Capture baseline frame time117 - Note spike frequency118 - Check allocation / GC evidence119 - Record peak concurrent active object count1201212. Identify candidate object types.122 - short-lived reusable123 - long-lived but stable124 - not worth pooling1251263. Define pool boundary.127 - per scene128 - per gameplay system129 - shared service only if multiple consumers truly need the same lifecycle rules1301314. Define the pool API.132 Typical surface:133 - `Get()`134 - `Release()`135 - `Prewarm(count)`136 - exhaustion policy (`expand`, `fallback instantiate`, or `drop request`)1371385. Define lifecycle hooks.139 - `OnAcquire`140 - `OnRelease`141 - `ResetState`1421436. Write the reset contract before implementation.144 Review at minimum:145 - transform / position / rotation / scale146 - visibility and z-order147 - velocity / movement state148 - timers / tweens / animation state149 - collision and hitbox state150 - text / UI content151 - signal or event subscriptions152 - async / cancellation state153 - parent attachment / process mode / layer or canvas state1541557. Integrate with the target engine safely.156 - identify which object lifecycle rules are engine-native and which are app-owned157 - prefer explicit activation/deactivation over magical hidden reuse158 - avoid duplicate event or signal connections on reuse159 - keep world-space and UI-space lifecycles separate160 - if the task is Godot-specific, use `references/godot-reference.md` for scene-tree and signal details1611628. Add safety checks.163 - double-release guard164 - missing-release detection165 - pool exhaustion behavior166 - debug counters or structured logging where helpful1671689. Re-profile with the same scenario.169 Keep the pool only if the gain is measurable and the lifecycle remains understandable.170171## Output contract172173Return the result using `assets/object-pool-brief.md` in this section order.174175When using this skill, return these sections:1761771. **Candidate analysis**1782. **Pool design**1793. **Reset contract**1804. **Engine integration notes**1815. **Migration steps**1826. **Benchmark plan**183184## Engine-specific notes185186### Godot / .NET187188- `Node` lifecycle safety matters more than clever pooling.189- Reused nodes can leak state through:190 - signals191 - child nodes192 - tweens193 - animation state194 - stale parent attachment195 - pending async callbacks196- For UI recycling, verify:197 - text198 - focus199 - bindings200 - visibility201 - layout assumptions202- For gameplay recycling, verify:203 - transform204 - collision205 - process state206 - timers207 - callbacks208- If pooling removes GC spikes but makes behavior nondeterministic, the design is not done yet.209- Use `references/godot-reference.md` when you need concrete guidance on `_Ready()` vs `_EnterTree()`, `RequestReady()`, release strategies, async ghost callbacks, or shared-resource contamination.210211If the target runtime is not Godot/.NET, translate these notes into the equivalent lifecycle and ownership model instead of copying Node-specific advice verbatim.212213## Common pitfalls214215- pooling everything blindly216- adding a global pool before identifying a hot path217- missing one reset responsibility and leaking state across uses218- allowing unbounded growth with no visibility219- mixing unrelated lifecycles in one pool220- keeping pooling after measurements show no material win221222## Companion files223224- `assets/object-pool-brief.md` — reusable output template for returning the pooling implementation or review artifact225- `references/godot-reference.md` — Godot-specific lifecycle, signal, timer, async, and resource-sharing cautions for pooled nodes226227## Validation228229A good result should satisfy all of the following:230231- simpler non-pooling alternatives were considered first232- pooling candidates were justified by evidence, not instinct233- reset rules and ownership boundaries are explicit enough to review234- exhaustion behavior is defined235- before/after verification is included236- the proposed pooling keeps the codebase understandable237238## Completion rule239240This skill is complete when the agent has:241242- decided whether pooling is justified at all243- identified what should and should not be pooled244- defined the ownership boundary, API, exhaustion behavior, and reset contract245- described engine lifecycle and integration risks clearly246- returned a concrete migration and benchmark plan