using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;


public class ObjectPoolManager : MonoBehaviour

{

    [System.Serializable]

    public class Pool

    {

        public string tag;

        public GameObject prefab;

        public int size;

    }

    #region Singleton

    public static ObjectPoolManager Instance;

    private void Awake()

    {

        if (Instance != null)

        {

            //if (Instance != this)

            //{

            //    Destroy(this.gameObject);

            //}

        }

        else

        {

            Instance = this;

           // DontDestroyOnLoad(this);

        }

        poolDictionary = new Dictionary<string, myPriorityQueue>();


        foreach (Pool pool in pools)

        {

            myPriorityQueue objectPool = new myPriorityQueue();

            for (int i = 0; i < pool.size; i++)

            {

                GameObject obj = Instantiate(pool.prefab, gameObject.transform);

                obj.SetActive(false);

                obj.transform.SetParent(this.transform);

                objectPool.Push(obj);

            }

            poolDictionary.Add(pool.tag, objectPool);

        }

    }

    #endregion

    public List<Pool> pools;

    public Dictionary<string, myPriorityQueue> poolDictionary=new Dictionary<string, myPriorityQueue>();

    

    public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)

    {

        if (!poolDictionary.ContainsKey(tag))

        {

#if UNITY_EDITOR

            Debug.LogWarning("Pool withh tag " + tag + "doesn't excist.");

#endif

            return null;

        }

        GameObject objectToSpawn = poolDictionary[tag].top();

        poolDictionary[tag].delete();

        objectToSpawn.transform.position = position;

        objectToSpawn.transform.rotation = rotation;

        objectToSpawn.SetActive(true);

        IPooledObject pooledObj = objectToSpawn.GetComponent<IPooledObject>();

        if (pooledObj != null)

        {

            pooledObj.OnObjectSpawn();

        }

       poolDictionary[tag].Push(objectToSpawn);

        return objectToSpawn;

    }

    public void AddPool(string tag,GameObject obj)

    {

        poolDictionary[tag].Push(obj);

    }

    public class myPriorityQueue 

    {


        private List<GameObject> q = new List<GameObject>();

        public int Count = 0;

        private GameObject temp;

        public void swap(int a, int b)

        {

            temp = q[a];

            q[a] = q[b];

            q[b] = temp;

        }

        public void Push(GameObject n)

        {

            // 힙의 맨 끝에 새로운 데이터를 삽입한다.

            q.Add(n);

            Count++;

            int now = q.Count - 1;  // 추가한 노드의 위치. 힙의 맨 끝에서 시작.


            // 위로 도장 깨기 시작

            while (now > 0)

            {

                int next = (now - 1) / 2;  // 부모 노드

                if(q[now].activeSelf&&!q[next].activeSelf)//부모가 비활성화고 자식이 활성화면 멈춤.

                {

                    break;

                }

                // 두 값을 서로 자리 바꿈

                swap(now, next);


                // 검사 위치로 이동한다.

                now = next;

            }


        }


        public GameObject top()

        {


            return q[0];

        }

        public GameObject delete()

        {

            GameObject t = q[0];

            q[0] = q[q.Count - 1];

            q.RemoveAt(q.Count - 1);

            int lastIndex = q.Count - 1;

            Count--;

            int now = 0;

            while (true)

            {

                int left = 2 * now + 1;

                int right = 2 * now + 2;


                int next = now;

                // 왼쪽 값이 현재값보다 크면, 왼쪽으로 이동

                if (left <= lastIndex && q[next].activeSelf&&!q[left].activeSelf)//연산자 바꾸면 반대

                {

                    //부모가 활성화고 자식이 비활성화면 이동

                    next = left;

                }

                // 오른쪽 값이 현재값(왼쪽 이동 포함)보다 크면, 오른쪽으로 이동

                if (right <= lastIndex && q[next].activeSelf && !q[right].activeSelf)//연산자 반대로 

                    next = right;


                // 왼쪽/오른쪽 모두 현재값보다 작으면 종료

                if (next == now)

                    break;


                // 두 값 서로 자리 바꿈

                swap(next, now);


                // 검사 위치로 이동한다.

                now = next;

            }

            return t;

        }

    }

}


사실 유니티는 안에 풀링 쓰라고 만든 거 있는데 using UnityEngine.Pool;
저거 안쓰고 위에 코드(난 브래키스 형님꺼가 편해서) 이거씀. 쓰다가 이건 이제 무조건 순서대로 가서
우선순위 큐 적용하면 괜찮을 것 같아서 이런식으로 만들었는데 단점이 있을까?
테스트해보니 생각대로 잘동작은 하는데 흠... ㅠ