BIT Nurse - Networked Gameplay Programming Consultant

GameObject Pool

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.

Why Pooling

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.

Code Example

This Script is run on a permanent GameObject that is hidden in the game world.

 using System.Collections.Generic; 

 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 

 }