AgentSkillsCN

object-pooling-system

通过对象池技术高效管理 GameObject,大幅降低垃圾回收峰值与内存分配开销。

SKILL.md
--- frontmatter
name: object-pooling-system
description: "High-performance object pooling for GameObjects to eliminate GC spikes and allocation overhead."
version: 1.0.0
tags: ["performance", "pooling", "memory", "GC", "optimization"]
argument-hint: "prefab='Bullet' initial_size='20' OR pool_type='generic'"
disable-model-invocation: false
user-invocable: true
allowed-tools:
  - run_command
  - list_dir
  - write_to_file

Object Pooling System

Overview

High-performance object pooling to eliminate GC spikes from Instantiate/Destroy. Essential for projectiles, particles, enemies, and any frequently spawned objects.

When to Use

  • Use for bullets, projectiles, VFX
  • Use for spawned enemies, pickups
  • Use for UI list items
  • Use when experiencing GC spikes
  • Use for mobile/console optimization

Architecture

code
┌─────────────────────────────────────────────────────────────┐
│                   POOLING ARCHITECTURE                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  POOL MANAGER              OBJECT POOLS                     │
│  ┌──────────────┐         ┌──────────────┐                 │
│  │ GetPool<T>() │────────▶│ Pool<Bullet> │                 │
│  │ RegisterPool │         │  ├─ Active[] │                 │
│  │ ReturnAll()  │         │  └─ Available│                 │
│  └──────────────┘         │     Queue<>  │                 │
│                           ├──────────────┤                 │
│  POOLABLE OBJECT          │ Pool<Enemy>  │                 │
│  ┌──────────────┐         └──────────────┘                 │
│  │ IPoolable    │                                          │
│  │  OnSpawn()   │◀────────── Get()                        │
│  │  OnDespawn() │──────────▶ Return()                     │
│  └──────────────┘                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Pool Types

TypeUse Case
Simple PoolSingle prefab, fixed size
Generic PoolType-safe, any MonoBehaviour
ExpandableGrows when exhausted
Multi-PoolMultiple prefab variants

Performance Impact

OperationWithout PoolWith Pool
Spawn 100~5ms~0.1ms
GC Alloc100KB+0KB
Memory churnHighNone

Best Practices

  • ✅ Pre-warm pools at scene load
  • ✅ Use IPoolable for reset logic
  • ✅ Return objects explicitly
  • ✅ Set reasonable initial sizes
  • ✅ Use component caching
  • NEVER Destroy pooled objects
  • NEVER forget to return objects
  • NEVER use GetComponent on spawn

Few-Shot Examples

Example 1: Generic Pool

User: "Pool for bullets."

Agent:

csharp
public class ObjectPool<T> where T : MonoBehaviour, IPoolable
{
    private readonly T _prefab;
    private readonly Queue<T> _available = new();
    private readonly List<T> _active = new();
    private readonly Transform _parent;
    
    public ObjectPool(T prefab, int initialSize, Transform parent = null)
    {
        _prefab = prefab;
        _parent = parent;
        
        for (int i = 0; i < initialSize; i++)
        {
            CreateInstance();
        }
    }
    
    public T Get(Vector3 position, Quaternion rotation)
    {
        T obj = _available.Count > 0 ? _available.Dequeue() : CreateInstance();
        obj.transform.SetPositionAndRotation(position, rotation);
        obj.gameObject.SetActive(true);
        obj.OnSpawn();
        _active.Add(obj);
        return obj;
    }
    
    public void Return(T obj)
    {
        obj.OnDespawn();
        obj.gameObject.SetActive(false);
        _active.Remove(obj);
        _available.Enqueue(obj);
    }
}

Example 2: IPoolable Interface

User: "Reset logic for pooled object."

Agent:

csharp
public interface IPoolable
{
    void OnSpawn();
    void OnDespawn();
}

public class Bullet : MonoBehaviour, IPoolable
{
    private Rigidbody _rb;
    private TrailRenderer _trail;
    
    private void Awake()
    {
        _rb = GetComponent<Rigidbody>();
        _trail = GetComponent<TrailRenderer>();
    }
    
    public void OnSpawn()
    {
        _rb.velocity = Vector3.zero;
        _trail.Clear();
    }
    
    public void OnDespawn()
    {
        _rb.velocity = Vector3.zero;
    }
}

Example 3: Pool Manager Singleton

User: "Centralized pool management."

Agent:

csharp
public class PoolManager : MonoBehaviour
{
    private static PoolManager _instance;
    private readonly Dictionary<Type, object> _pools = new();
    
    public static ObjectPool<T> GetPool<T>() where T : MonoBehaviour, IPoolable
    {
        return (ObjectPool<T>)_instance._pools[typeof(T)];
    }
    
    public void RegisterPool<T>(T prefab, int size) where T : MonoBehaviour, IPoolable
    {
        var pool = new ObjectPool<T>(prefab, size, transform);
        _pools[typeof(T)] = pool;
    }
}

Related Skills

  • @addressables-asset-management - Async prefab loading
  • @memory-profiler-expert - Verify pool effectiveness
  • @mobile-optimization - Mobile-specific pooling