I’m using a factory . here is how i do it for anyone who want to know .
I really think this is an efficient solution u can just copy and paste the 2 scripts and add the first script
(objectPool script) to an object in your scene .(i jsut added it to my core since it will be in every scene )
namespace RPG.Core{
public class ObjectPool : MonoBehaviour
{//this iscript is for instanciating prefabs at the start of the game and using them instead of constantly instantiating and destroing them this way we save performance
public static ObjectPool instance;//this allowes us to call this from everiwhere
[SerializeField] private GameObject[] prefabs;//the prefab we need to instanciating the dictionary and queess
[SerializeField] private int poolSize=200;
public Dictionary<GameObject,Queue<GameObject>> poolDictionary = new Dictionary<GameObject, Queue<GameObject>>();
private void Awake()
{
if (instance == null)//this makes sure we know what instance we are using
{
instance=this;
}
else
Destroy(instance);
InitializeDictionaryQueues();
}
public void ReturnGameObjectToPool(GameObject gameObjectToReturn)//returns gameobject to proper pool
{
GameObject originalPrefab=gameObjectToReturn.GetComponent<PooledGameObject>().originalPrefab;
gameObjectToReturn.SetActive(false);
poolDictionary[originalPrefab].Enqueue(gameObjectToReturn);
gameObjectToReturn.transform.parent=transform;
}
public GameObject GetGameObject(GameObject gameObjectToSearch)//finds a specific gameobject and activates,if theres no pool for it it creates one ,if empty instantiate new
{
if(!poolDictionary.ContainsKey(gameObjectToSearch))
{
CreateDictionaryPool(gameObjectToSearch);
}
if(poolDictionary[gameObjectToSearch].Count==0)
{
CreateNewGameObject(gameObjectToSearch);
}
GameObject gameObjectToGet= poolDictionary[gameObjectToSearch].Dequeue();
gameObjectToGet.SetActive(true);
gameObjectToGet.transform.parent=null;
return gameObjectToGet;
}
private void CreateDictionaryPool(GameObject prefab)//we are instantiating the prefab all at once so we dont have to create or destroy them later
{
poolDictionary[prefab]=new Queue<GameObject>();
for (int i = 0;i<poolSize;i++)
{
CreateNewGameObject(prefab);
}
}
private void CreateNewGameObject(GameObject prefab)//creates a copy of the prefab
{
GameObject newGameObject=Instantiate(prefab ,transform);
newGameObject.AddComponent<PooledGameObject>().originalPrefab=prefab;//adds original prefab to clones so we can serach the pools with it(clone its not the same as original)
newGameObject.gameObject.SetActive(false);
poolDictionary[prefab].Enqueue(newGameObject);//adding the new instanciated bullet to the q
}
private void InitializeDictionaryQueues()//initialize all the pools for the prefabs
{
foreach (var prefab in prefabs)
{
CreateDictionaryPool(prefab);
}
}
}
}
when u use the function GetGameObject() the script will take enable a new object .if there are no object of this type available it will create one for u and set it up so it can be reused so u will never run out of objects and u will not have to create them all the time either in the script there’s also a way to instantiate prefabs on awake if u give them the prefabs b4 hand .
public class PooledGameObject: MonoBehaviour
{//this is used for the object pooling so that it can identifie the original prefab of the clone and use it as a key to search in the dictionary
public GameObject originalPrefab{ get; set; }
}
so in conclusion we make this 2 scripts and we add the first to an empty object in the scene .
after that where we we were instantiating something we use this
RPG.Core.ObjectPool.instance.GetGameObject(Gameobject gameobject );
and instead of destroy we use this
RPG.Core.ObjectPool.instance.ReturnGameObjectToPool(gameObject);
the rpg.core is the namespace u probably have ur own .
heres a function u can use for timer destroy
IEnumerator ReturnToPoolTimer(GameObject gameObject,int time )//returns object to pool after a time
{
yield return new WaitForSeconds(time);
RPG.Core.ObjectPool.instance.ReturnGameObjectToPool(gameObject);
}
let me know if you have any questions on this