커스텀 오브젝트 풀링

	public class MyObjectPool : MonoBehaviour, IMyObjectPool
	{
			[SerializeField] private int _initialSize = 1;          // 초기 풀 크기
			[SerializeField] private Transform _folder;
			
			private Dictionary<string, Queue<GameObject>> _poolDict = new();
			private Dictionary<string, List<GameObject>> _activeItemDict = new();
			
			private const string PRIMARY_KEY = "Primary";
			
			private void Awake()
			{
			    if (_folder == null)
			        _folder = transform;
			}
			
			public void SetPool(GameObject prefab, string key = PRIMARY_KEY)
			{
			    if (!_poolDict.ContainsKey(key))
			    {
			        _poolDict[key] = new();
			        _activeItemDict[key] = new();
			    }
			
			    // 초기 풀 크기만큼 오브젝트 생성하여 풀에 저장
			    for (int i = 0; i < _initialSize; i++)
			        CreatePooledItem(prefab, key);
			}
			
			// 오브젝트 생성 후 풀에 추가
			private GameObject CreatePooledItem(GameObject prefab, string key = PRIMARY_KEY)
			{
			    Queue<GameObject> pool = _poolDict[key];
			
			    GameObject obj = Instantiate(prefab, _folder, true);
			    obj.gameObject.SetActive(false);
			    pool.Enqueue(obj);
			    return obj;
			}
			
			// 오브젝트를 풀에서 가져오기
			public GameObject Get(GameObject prefab, string key = PRIMARY_KEY)
			{
			    Queue<GameObject> pool = _poolDict[key];
			    if (pool.Count == 0)
			    {
			        CreatePooledItem(prefab, key);
			    }
			    GameObject pooledObject = pool.Dequeue();
			    pooledObject.gameObject.SetActive(true);
			
			    _activeItemDict[key].Add(pooledObject);
			    return pooledObject;
			}
			
			// 오브젝트를 풀에 반환하기
			public void Release(GameObject pooledObject, string key = PRIMARY_KEY)
			{
			    if (!IsValidKey(key))
			        return;
			
			    pooledObject.gameObject.SetActive(false);
			    _poolDict[key].Enqueue(pooledObject);
			    _activeItemDict[key].Remove(pooledObject);
			}
			
			// 모든 오브젝트를 풀에 반환
			public void Clear(string key = PRIMARY_KEY)
			{
			    if (!IsValidKey(key))
			        return;
			
			    // 리스트의 뒤에서부터 요소를 하나씩 Release하고 제거
			    for (int i = _activeItemDict[key].Count - 1; i >= 0; i--)
			        Release(_activeItemDict[key][i], key);
			
			    _activeItemDict[key].Clear();
			}
			
			// 모든 풀을 반환
			public void ClearAll()
			{
			    foreach (var key in _poolDict.Keys)
			        Clear(key);
			}
			
			// 모든 오브젝트를 제거
			public void DestroyAll(string key = PRIMARY_KEY)
			{
			    if (!IsValidKey(key))
			        return;
			
			    _activeItemDict[key].ForEach(obj => Destroy(obj));
			    _activeItemDict[key].Clear();
			
			    while (_poolDict[key].Count > 0)
			    {
			        GameObject obj = _poolDict[key].Dequeue();
			        if (obj != null)
			        {
			            Destroy(obj);
			        }
			    }
			}
			
			// 풀링된 오브젝트 개수 반환
			public int GetCount(string key = PRIMARY_KEY)
			{
			    if (!IsValidKey(key))
			        return 0;
			
			    return _poolDict[key].Count + _activeItemDict[key].Count;
			}
			
			// 활성화된 오브젝트 개수 반환
			public int GetActiveCount(string key = PRIMARY_KEY)
			{
			    if (!IsValidKey(key))
			        return 0;
			
			    return _activeItemDict[key].Count;
			}
			
			// 유효 키 검증
			private bool IsValidKey(string key)
			{
			    if (!_poolDict.ContainsKey(key) || !_activeItemDict.ContainsKey(key))
			    {
			        Debug.LogError($"키({key})가 존재하지 않습니다.");
			        return false;
			    }
			    else return true;
			}
	}
public interface IMyObjectPool
{
    public void SetPool(GameObject prefab, string key);
    public GameObject Get(GameObject prefab, string key);
    public void Release(GameObject pooledObject, string key);
    public void Clear(string key);
    public void ClearAll();
    public void DestroyAll(string key);
    public int GetCount(string key);
    public int GetActiveCount(string key);
}

샘플

[RequireComponent(typeof(IMyObjectPool))]
public class Sample_ObjectPool : MonoBehaviour
{
    [SerializeField] private GameObject _itemPrefab;
    private IMyObjectPool _pool;
    
    private void Awake()
    {
        _pool = transform.GetComponent<IMyObjectPool>();
    }

    private void Start() => Init();

    private void Init()
    {
        _pool.SetPool(_itemPrefab.gameObject, _itemPrefab.name);  // 오브젝트 & Key
    }

    public void Get() => _pool.Get(_itemPrefab.gameObject, (_itemPrefab.name);
    
    public void Release(GameObject item) => _pool.Release(item, _itemPrefab.name);
    
    public void Clear() => _pool.Clear(_itemPrefab.name);
    
    public void DestroyAll() => _pool.DestroyAll(_itemPrefab.name);