[Code][Unity3d] Quick And Dirty Object Pool Manager

Object pool managers are very useful when building optimized mobile games. Instantiating a new GameObject takes time, and when you have lots of objects to instantiate like bullets or ships you need a architecture that bypasses the the objects instantiation. The solution is simple: instantiate the objects and disable and enable them when needed.

ObjectPoolManager

I created a quick and dirty object pool manager that manages to reuse GameObject instances organized by tags. This means that when request from the pool manager a new instance is served based on the prefab tag provided. The idea it’s simple – create 2 lists of GameObject instances, one for the disabled objects one and another for the enabled ones. When you need an instance of an object with certain tag the pool manager tries to pull one from the disabled list, if none is found then it instantiate a new one based on the provided prefab.

To be more clear I’ll make and example of usage:

//"shipPrefab" it's the GameObject prefab provided
GameObject newShip = PoolManager.Instance.GetObject(shipPrefab);

Now it’s done. When you disable or enable the object the pool manager handles all things for you. Easy peasy lemon squeezy!

Now the magic behind this:

The PoolManager class looks like this. It is inheriting the Manager class that makes it behave like a singleton and can be access with static parameter Instance. In the next posts I’ll share the Manager class and give more in depth explanation. For now this is how it looks.

public class PoolManager : Manager<PoolManager> {

    #region Helpers
    public class Pool
    {
        public List<GameObject> enabled = new List<GameObject>();
        public List<GameObject> disabled = new List<GameObject>();

        public GameObject GetObject()
        {
            //check if disable has objects
            if(disabled.Count > 0)
            {
                //get the first one
                GameObject obj = disabled[0];

                //setActive
                obj.SetActive(true);

                return obj;
            }
            return null;
        }

        public GameObject AddNewObject(GameObject prefab)
        {
            //Create new instance
            GameObject obj = Instantiate(prefab);
            ObjectPoolable objPoolable = obj.AddComponent<ObjectPoolable>();
            objPoolable.SetPool(this);
            
            //add object to enabled
            enabled.Add(obj);

            //retun it
            return obj;
        }

        public void Enable(GameObject obj)
        {
            disabled.Remove(obj);
            enabled.Add(obj);
        }

        public void Disable(GameObject obj)
        {
            enabled.Remove(obj);
            disabled.Add(obj);
        }
    }
    #endregion

    #region Private Vars
    public List<string> tags = new List<string>();
    public List<Pool> objPools = new List<Pool>();
    #endregion

    public GameObject GetObject(GameObject prefab)
    {
        string tag = prefab.tag;

        GameObject obj;

        int index = tags.FindIndex(y => y == tag);

        if (index > -1)
        {
            //get the corect pool
            Pool pool = objPools[index];
            obj = pool.GetObject();

            //check if has disabled object, if not create a new one
            if (obj == null)
                obj = pool.AddNewObject(prefab);
        }
        else
        {
            //add new pool
            tags.Add(tag);
            Pool newPool = new Pool();
            objPools.Add(newPool);

            //Create a new instance of prefab
            obj = newPool.AddNewObject(prefab);
        }

        return obj;
    }
}

The trick to make the object pool manager simpler to use is to create a component (named ObjectPoolable) that attaches to the GameObject that is pooled and when the object gets disabled it auto pulls himself from the pool manager enabled list and adds it to the disabled list. Here’s the ObjectPoolable class:

public class ObjectPoolable : MonoBehaviour {

    #region Private Vars
    private PoolManager.Pool _pool;
    #endregion

    void OnEnable()
    {
        if (_pool != null)
            _pool.Enable(gameObject);
    }

    void OnDisable()
    {
        if (_pool != null)
            _pool.Disable(gameObject);
    }

    public void SetPool(PoolManager.Pool pool)
    {
        _pool = pool;
    }
}

On the link below can find the two .cs file needed for the object pool manager.

PoolManager_cs_files

Hope it helps. For any clarification and question don’t hesitate to use the comments section.

Leave a Reply

Your email address will not be published. Required fields are marked *