Object pools that can be configured in Unity

Configurable object pool

In many cases, we need to generate a large number of instances, such as the production of bullets, which will be destroyed. It is a waste of performance to continuously generate and destroy instances. We often use object pool technology to optimize this.

Next, the code is posted directly:

ObjectPoolList.cs

/// <summary>
///Inherit ScriptableObject and implement custom resource configuration file
/// </summary>
public class ObjectPoolList:ScriptableObject
{
    public List<ObjectPool> Poollist;
}

ObjectPool.cs

The purpose of using two lists in the code is to solve the problem. When only one list is used, each time an instance is obtained, it will traverse the current list to find whether there are idle instances. When the use pool is used up, the objects are stored in the idle pool. When the idle pool needs to be used, the objects will be transferred to the use pool. This is a way of exchanging space for time.

/// <summary>
//Resource pool
/// </summary>
[Serializable]
public class ObjectPool {
    [SerializeField]
    private string obj_Name;
    [SerializeField]
    private int obj_Amount;
    [SerializeField]
    private GameObject obj_Prefab;

    public string Name
    {
        get
        {
            return obj_Name;
        }
    }

    //Idle pool
    [NonSerialized]
    public List<GameObject> leisurePoolList = new List<GameObject>();

    //Use pool
    [NonSerialized]
    public List<GameObject> usingPoolList = new List<GameObject>();

    /// <summary>
    ///Idle pool transferred to use pool
    /// </summary>
    private GameObject UsingPool()
    {
        GameObject obj = leisurePoolList[0];
        obj.SetActive(true);
        usingPoolList.Add(leisurePoolList[0]);
        leisurePoolList.RemoveAt(0);
        return obj;
    }

    /// <summary>
    ///Use pool to transfer to idle pool
    /// </summary>
    /// <param name="obj"></param>
    public void LeiSurePool(GameObject obj)
    {
        usingPoolList.Remove(obj);
        leisurePoolList.Add(obj);
    }

    /// <summary>
    ///Return instances in pool or generated
    /// </summary>
    /// <returns></returns>
    public GameObject GetInst()
    {
        if(usingPoolList.Count>=obj_Amount)
        {
            GameObject.Destroy(usingPoolList[0]);
            usingPoolList.RemoveAt(0);
        }
        if(leisurePoolList.Count==0)
        {
            GameObject newObj = GameObject.Instantiate(obj_Prefab);
            usingPoolList.Add(newObj);
            return newObj;
        }
        else
        {
            return UsingPool();
        }
    }
}

PoolManager.cs

This code gets the configured information in the configuration file, and gets the instance through GetInst()

public class PoolManager
{
    #region example
    private static PoolManager _instance;
    public static PoolManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new PoolManager();
            }
            return _instance;
        }
    }
    #endregion

    private static readonly string poolConfigPrefix = "Asset/Framework/Resources/";
    private static readonly string poolConfigName = "ObjectPoolConfig";
    private static readonly string poolConfigPostfix = ".asset";
    public Dictionary<string, ObjectPool> poolDic;

    public static string PoolConfigPath
    {
        get
        {
            return poolConfigPrefix + poolConfigName + poolConfigPostfix;
        }
    }

    private PoolManager()
    {
        ObjectPoolList poolList = Resources.Load<ObjectPoolList>(poolConfigName);
        poolDic = new Dictionary<string, ObjectPool>();

        foreach(ObjectPool pool in poolList.Poollist)
        {
            poolDic.Add(pool.Name, pool);
        }

        Init();
    }

    private void Init()
    {
        //TODO
    }

    /// <summary>
    ///Get an instance of poolName
    /// </summary>
    /// <param name="poolName"></param>
    /// <returns></returns>
    public GameObject GetInst(string poolName)
    {
        if(poolDic.ContainsKey(poolName))
        {
            return poolDic[poolName].GetInst();
        }

        Debug.LogError("poolname :" + poolName + "Non-existent");
        return null;
    }
}

ObjectPoolWindowEditor.cs

The following code should be placed in the Editor folder. Click Create PoolConfig under the Manager menu to generate a. asset configuration file, as shown in the figure:

This configuration file can be used to configure the name, number, and prefab of objects in the object pool.

public class ObjectPoolWindowEditor
{
    [MenuItem("Manager/Create PoolConfig")]
    static void CreatePool()
    {
        ObjectPoolList poolList = ScriptableObject.CreateInstance<ObjectPoolList>();
        AssetDatabase.CreateAsset(poolList, PoolManager.PoolConfigPath);
        AssetDatabase.SaveAssets();
    }
}

In the outside world, you only need PoolManager.Instance.GetInst("your prefab name"); to get an instance of the object.

Posted by simenss on Wed, 06 Nov 2019 10:04:12 -0800