Base abstract class contains logic for spawning and despawning game objects from a pool by giving it an enum entry, and creating pools of those game object.
An object implementing this abstract class will be capable to host multiple pools of game objects with each of the pools defined by an entry inside the enum (generic T).
The basic pool that this class creates is defined in the PoolClasses.cs.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ObjectPooling
{
/// <summary>
/// Base object pooler class for a generic enum. All other pools inherit from this class.
/// </summary>
/// <typeparam name="T"> Enum defining types for a implementation of the pool. </typeparam>
[System.Serializable]
public abstract class ObjectPoolerBase<T> : MonoBehaviour where T : struct, System.IConvertible
{
/// <summary>
/// List of items i am creating pools of.
/// </summary>
[SerializeField]
protected List<ObjectPoolBase<T>> itemsToPool = new List<ObjectPoolBase<T>>();
/// <summary>
/// Dictionary linking pools parent transform with the <see cref="T"/>.
/// </summary>
private Dictionary<T, GameObject> pooledObjectsParents = new Dictionary<T, GameObject>();
/// <summary>
/// Dictionary linking the pools with the <see cref="PoolType"/>.
/// </summary>
private Dictionary<T, Queue<GameObject>> pooledObjectsQueue = new Dictionary<T, Queue<GameObject>>();
/// <summary>
/// Dictionary linking the pools information class <see cref="ObjectPoolItem"/> with its <see cref="PoolType"/>
/// </summary>
private Dictionary<T, ObjectPoolBase<T>> poolItemDictionary = new Dictionary<T, ObjectPoolBase<T>>();
/// <summary>
/// Creating the pools and populating the dictionary's: <see cref="pooledObjectsParents"/>, <see cref="pooledObjectsQueue"/>, <see cref="poolItemDictionary"/>.
/// </summary>
private void Start()
{
foreach (ObjectPoolBase<T> item in itemsToPool)
{
GameObject poolParent = new GameObject(item.ReturnType().ToString() + "Parent");
poolParent.transform.SetParent(this.transform);
Queue<GameObject> pool = new Queue<GameObject>();
PopulateDictionarys(item, poolParent, pool);
for (int i = 0; i < item.amountToPool; i++)
{
AddToPool(pool, item, poolParent.transform);
}
}
}
/// <summary>
/// Method that populates all <see cref="Dictionary{TKey, TValue}"/>'s needed for the functioning of the pooler.
/// </summary>
/// <param name="item"> The item for <see cref="poolItemDictionary"/>. </param>
/// <param name="poolParent"> The transform that is the parent of instantiated objects for <see cref="pooledObjectsParents"/>. </param>
/// <param name="pool"> The pool for <see cref="pooledObjectsQueue"/>. </param>
protected virtual void PopulateDictionarys(ObjectPoolBase<T> item, GameObject poolParent, Queue<GameObject> pool)
{
T type = item.ReturnType();
pooledObjectsParents.Add(type, poolParent);
pooledObjectsQueue.Add(type, pool);
poolItemDictionary.Add(type, item);
}
#region secondarySpawnFromPoolMethods
public GameObject SpawnFromPool(T poolType)
{
return SpawnFromPool(poolType, Vector3.zero, Quaternion.identity, null);
}
public GameObject SpawnFromPool(T poolType, Vector3 position)
{
return SpawnFromPool(poolType, position, Quaternion.identity, null);
}
public GameObject SpawnFromPool(T poolType, Transform parent)
{
return SpawnFromPool(poolType, Vector3.zero, Quaternion.identity, parent);
}
public GameObject SpawnFromPool(T poolType, Vector3 position, Quaternion rotation)
{
return SpawnFromPool(poolType, position, rotation, null);
}
#endregion
/// <summary>
/// Spawning an object from a pool.
/// </summary>
/// <param name="poolType"> Type of the object that is pooled. </param>
/// <param name="position"> The local position it gets spawned in. </param>
/// <param name="rotation"> The local rotation it gets spawned in.</param>
/// <param name="parent"> The transform that will be the child of the spawned item. </param>
/// <returns> Returns the spawned object or null if the pool is empty and cant be expanded.</returns>
public virtual GameObject SpawnFromPool(T poolType, Vector3 position, Quaternion rotation, Transform parent)
{
pooledObjectsQueue.TryGetValue(poolType, out Queue<GameObject> pool);
if (pool.Count <= 0)
{
poolItemDictionary.TryGetValue(poolType, out ObjectPoolBase<T> item);
if (item.shouldExpand)
{
AddToPool(pool, item, null);
return Spawn(pool, position, rotation, parent);
}
return null;
}
else
{
return Spawn(pool, position, rotation, parent);
}
}
/// <summary>
/// Returning an object to its dedicated pool.
/// </summary>
/// <param name="poolType"> Pool type of the object. </param>
/// <param name="gameObject"> The object that is returning. </param>
public virtual void ReturnToPool(T poolType, GameObject gameObject)
{
pooledObjectsQueue.TryGetValue(poolType, out Queue<GameObject> pool);
pooledObjectsParents.TryGetValue(poolType, out GameObject parent);
gameObject.transform.SetParent(parent.transform);
gameObject.SetActive(false);
pool.Enqueue(gameObject);
}
/// <summary>
/// Ads a new object to a pool.
/// </summary>
/// <param name="pool">The pool the object should be added to.</param>
/// <param name="item">The items information class.</param>
/// <param name="parent">The parent that holds the pool.</param>
protected virtual void AddToPool(Queue<GameObject> pool, ObjectPoolBase<T> item, Transform parent)
{
InstantiateObjectToPool(pool, item, parent);
}
/// <summary>
/// Class that instantiates a new object to a designated pool.
/// </summary>
/// <param name="pool"> The pool the instantiated object will be added to. </param>
/// <param name="item"> The <see cref="ObjectPoolBase{T}"/> item that is used as a template for instantiation. </param>
/// <param name="parent"> The parent transform that will hold the instantiated object in the hierarchy. </param>
/// <returns> The instantiated game object. </returns>
protected virtual GameObject InstantiateObjectToPool(Queue<GameObject> pool, ObjectPoolBase<T> item, Transform parent)
{
GameObject obj = (GameObject)Instantiate(item.objectToPool);
obj.transform.SetParent(parent);
obj.SetActive(false);
pool.Enqueue(obj);
return obj;
}
/// <summary>
/// Handles spawning of an object. Used in <see cref="SpawnFromPool(PoolType, Vector3, Quaternion, Transform)"/>.
/// </summary>
/// <param name="pool"> The pool it spawns from.</param>
/// <param name="position"> The local position it will be spawned in.</param>
/// <param name="rotation"> The local rotation it will be spawned in.</param>
/// <param name="parent"> The transform that will be its parent after spawning. </param>
/// <returns> The spawned game object. </returns>
private GameObject Spawn(Queue<GameObject> pool, Vector3 position, Quaternion rotation, Transform parent)
{
GameObject spawiningObject = pool.Dequeue();
spawiningObject.SetActive(true);
spawiningObject.transform.SetParent(parent);
spawiningObject.transform.localPosition = position;
spawiningObject.transform.localRotation = rotation;
return spawiningObject;
}
}
}