What is Pooling
Pooling of GameObjects means that many GameObjects are instantiated and hidden away in the gameworld.
All the hidden GameObjects are kept in a stack and when one of them is needed it's taken from its hidden state to be used and then reset and hidden again when the game is done with it.
Instantiating GameObjects is heavy for the game engine, instantiating many GameObjects simultaneously will cause stutter and make your game feel badly optimized.
Instead of instantiating and destroying GameObjects it is much better practice to just reset them and hide them until the next use.
Stack: Pop and Push
The best way to code an object pool is to keep a Stack with the GameObjects.
When you Pop a GameObject from the Stack it will actually take the GameObject away from the Stack, that way you cannot accidentally use a pooled GameObject that is already in use.
When Popping the last GameObject from the stack we use that one to instantiate a new GameObject that we Push onto the stack. That will increase the total number of GameObjects for the pool.
When Pushing a GameObject on to the stack it will place it on top of the stack again.
This Script is run on a permanent GameObject that is hidden in the game world.
public GameObject prefab; // set the GameObject to pool in the Editor
private Stack<GameObject> pool = new Stack<GameObject>();
internal void InstantiatePool(int amount) // call this to fill the stack with x amount
for (int i = 0; i < amount; i++) // runs this code "amount" times
GameObject instance = Instantiate(prefab); // instantiate prefab into a GameObject (GO)
instance.SetActive(false); // deactivate the new GO
instance.transform.parent = parent; // child the new GO to the spell pool GameObject
pool.Push(instance); // put the GO onto the stack
internal GameObject GetPooledGO() // called from a script that want to use a pooled GO
if (pool.Count == 1) if there is only 1 GameObject left in the stack, run this code
InstantiatePool(1); // instantiate 1 more GameObject onto the stack.
GameObject pooledGO = pool.Pop(); // takes a GO out of the stack and allocates it pooledGO
return pooledGO; // sets the pooled GO as the reference in the script that called this method
internal void ReturnToPool(GameObject returnGO) // called from a script that has finished using a pooled GO
returnGO.SetActive(false); // deactivate GO
returnGO.transform.parent = parent; // moved back as child to pool GO
pool.Push(returnGO); // insert GO reference onto stack