Object Pooling in Unity

In my previous post, I covered object pooling in CoronaSDK. This article will cover object pooling in Unity, using C#. While the concept of Object Pooling is the same no matter what language, there are obvious syntax and set-up differences, and we’ll cover those Unity specific things here.

I am going to demonstrate a very simple object pooling class to get you started. There are more robust solutions on the Internet and in the Unity Asset Store, and each solution is a bit different, but this is what I have been using and it demonstrates the concept as well.

Step 1 – Initial Set Up

To use this solution, you need a couple of things:

  1. A prefab object that you will use as the object to pool. For this example, we’ll just create a cube, and we’ll call it “EnemyPrefab”.
  2. An empty Game Object. For this example, let’s rename it to “EnemyPool”.

Once you have a prefab and an empty game object, create a new C# script called Pooler. Here is the code for this script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Pooler : MonoBehaviour {
	
	public GameObject pooledObject;		// object to pool, drag into Inspector
	public int pooledAmount;			// number of objects, drag into Inspector
	public string objectName;			// name of object, enter into Inspector
	
	private List<GameObject> pooledObjects;
	
	/// <summary>
	/// Inits the object pool.  Renames the pool objects to the objectName
	/// </summary>
	void Awake () {
		pooledObjects = new List<GameObject>();
		for (int i = 0; i < pooledAmount; i++) {
			GameObject obj = (GameObject)Instantiate(pooledObject, Vector3.zero, Quaternion.identity);
			if (objectName != "") obj.name = objectName;
			obj.SetActive(false);
			pooledObjects.Add(obj);
		}
	}

	/// <summary>
	/// Gets the pooled object.
	/// </summary>
	/// <returns>The pooled object or null if all objects are used.</returns>
	public GameObject GetPooledObject() {
		for (int i = 0; i < pooledObjects.Count; i++) {
			if (!pooledObjects[i].activeInHierarchy) {
				return pooledObjects[i];
			}
		}
		
		return null;
	}
}
 Step 2: Pool your Prefab

Pooler PropertiesAttach the Pooler script to the empty game object, and look at the Inspector. You will notice 3 public properties:

  • Pooled Object – drag your prefab here. This is the object you want to pool.
  • Pooled Amount – enter the number of pooled prefabs you want.
  • Object Name – the name of the object. More on that later

Pooler HierarchyWhen your project is run, you will see a number of pooled objects in your Hierarchy view.

See line 20? I like to rename my objects when they are created, but this is up to you how to rename them, if at all. If you enter text in the Object Name property, the object is renamed.

Step 3: Use Objects in Pool

To get an object in the pool:

GameObject obj = GameObject.Find("EnemyPool").GetComponent<Pooler>().GetPooledObject();

or, to break it down:

GameObject gameObj = GameObject.Find("enemyPool");
Pooler enemyPool = gameObj.GetComponent<Pooler>();
GameObject pooledObject = enemyPool.GetPooledObject();

To return an object to the pool, inactivate it:

gameObj.SetActive(false);
That’s it!

There you have a very simple object pooler class. Of course you can expand on this class to do all sorts of things: update other properties, allow the class to grow if needed, etc.

6 thoughts on “Object Pooling in Unity”

    • Good catch… Pooled Objects is where the created objects are stored. It could be either private or prepended with “[HideInInspector]” so it does not show up in the Inspector. I will make that change.

      Note that I also have an update to this article here.

      Thanks for your comment!

      • One more quick question. I was wondering how I would properly apply your ObjectPooler script to this tutorial I’ve been trying to work on for a Match-3 Puzzle. Any help you could provide would be most appreciated, because I want to finish this tutorial, but right now all these Instantiate and Destroy calls are crashing Unity.

        In this snippet of the script, most of my Instantiate calls look like this:

        void Start () {

        piecePrefabDict = new Dictionary();

        for(int i = 0; i < piecePrefabs.Length; i++)
        {
        //check to see if our key is already in the dictionary. Key is the piece type
        if(!piecePrefabDict.ContainsKey(piecePrefabs[i].type))
        {
        piecePrefabDict.Add (piecePrefabs[i].type, piecePrefabs[i].prefab);
        }
        }

        for (int x = 0; x < xDim; x++)
        {
        for (int y = 0; y < yDim; y++)
        {
        //////////Here's my instantiation problem//////////
        GameObject background = (GameObject)Instantiate(backgroundPrefab, GetWorldPosition(x, y), Quaternion.identity);

        background.transform.parent = transform;
        }
        }

        And most of my Destroy calls look like this:

        }

        public bool FillStep()
        {

        if (pieceBelow.Type == PieceType.EMPTY)
        {
        //////////And here's my Destroy problem//////////
        Destroy (pieceBelow.gameObject);
        piece.MovableComponent.Move (x, y + 1, fillTime);
        pieces [x, y + 1] = piece;
        SpawnNewPiece (x, y, PieceType.EMPTY);
        movedPiece = true;
        }
        }

        if (pieceBelow.Type == PieceType.EMPTY)
        {
        ///////////Another Destroy call //////////

        Destroy (pieceBelow.gameObject);

        //////////And one more Instantiate call//////////

        GameObject newPiece = (GameObject)Instantiate(piecePrefabDict[PieceType.NORMAL], GetWorldPosition(x, -1), Quaternion.identity);

        }
        }

        Thanks again for any clarification you can provide.

  1. If Unity is crashing, that is probably due to a logic issue, not instantiating or destroying objects. For example, you may be destroying an object and still trying to reference it. Generally, my preference is to destroy objects as the last step in any method.

    Using the updated version of my Object Pooling class is simple… anywhere you use Instantiate, change that to a GetPooledObject call. Anywhere you use Destroy, change that to ReturnToPool. The script handles the rest.

    Hope this helps!

    • I’ll see what I can do about the logic issue asap. Unfortunately, I’m following a tutorial that is telling me exactly what logic to use and it’s so all over the place my system can’t handle it. But thanks a bunch! I’ll try to make the adjustments and see what I can do with it.

Leave a Reply to John Schumacher Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: