Get Your Personalized Game Dev Plan Tailored tips, tools, and next steps - just for you.

Implementing Object Pooling in Unity for Performance

Posted by Gemma Ellison
./
February 25, 2025
The cover for Implementing Object Pooling in Unity for Performance

Tired of seeing your frame rate plummet when the action heats up? Frequent object creation might be the silent performance killer. In game development, constant object creation and destruction can cripple performance, especially with complex objects or high object turnover. Object pooling offers a solution: reusing objects instead of endlessly creating and destroying them. This article details how to implement object pooling in Unity to boost game performance and cut down on garbage collection.

If you’re looking to optimize your game development workflow further, consider exploring tools like Wayline, a comprehensive platform designed to help developers succeed.

Understanding Object Pooling: The Core Concept

Object pooling is a design pattern where you maintain a collection of pre-instantiated objects ready for use. Instead of creating a new object when needed, you grab one from the pool. When finished, the object is returned to the pool instead of being destroyed.

One key benefit is reduced garbage collection. Reusing objects minimizes memory allocation, thus lowering overhead. Pooling also results in lower instantiation costs. Creating objects can be expensive. Pooling avoids these costs by reusing existing instances.

Object pooling shines when you frequently create and destroy the same type of object or when object creation is performance-intensive.

A photograph of a lush forest with many trees, representing the potential for memory management issues without object pooling

Don’t bother with object pooling if objects are created infrequently, object creation is lightweight, or you have ample memory and minimal performance constraints.

Implementing a Basic Object Pool in Unity

Here’s a basic GameObjectPool class in C#. It pre-instantiates a set of GameObjects and provides methods to retrieve and return them to the pool.

using System.Collections.Generic;
using UnityEngine;

public class GameObjectPool : MonoBehaviour
{
    public GameObject prefab;
    public int poolSize = 10;
    private List<GameObject> pool;

    void Start()
    {
        pool = new List<GameObject>();
        for (int i = 0; i < poolSize; i++)
        {
            GameObject obj = Instantiate(prefab);
            obj.SetActive(false);
            pool.Add(obj);
        }
    }

    public GameObject GetPooledObject()
    {
        for (int i = 0; i < pool.Count; i++)
        {
            if (!pool[i].activeInHierarchy)
            {
                return pool[i];
            }
        }

        // Expand the pool if needed
        GameObject obj = Instantiate(prefab);
        obj.SetActive(false);
        pool.Add(obj);
        Debug.LogWarning("Expanded object pool. Consider increasing initial pool size.");
        return obj;
    }

    public void ReturnToPool(GameObject obj)
    {
        obj.SetActive(false);
    }
}

This basic example dynamically grows the pool. Consider limiting the maximum pool size to prevent excessive memory usage.

Advanced Object Pooling Techniques

For more complex scenarios:

  • Generic Object Pools: A generic object pool allows you to create pools for different types of objects without writing separate pool classes for each type. This reduces code duplication and improves maintainability. The ObjectPool<T> class manages a pool of reusable components of type T. The constructor initializes the pool with a specified number of instances.

The following code creates a generic object pool in C# that can handle different types of objects.

using UnityEngine;
using System.Collections.Generic;

public class ObjectPool<T> where T : Component
{
    private List<T> pool;
    private T prefab;

    public ObjectPool(T prefab, int initialSize)
    {
        this.prefab = prefab;
        pool = new List<T>(initialSize);
        for (int i = 0; i < initialSize; i++)
        {
            T obj = GameObject.Instantiate(prefab);
            obj.gameObject.SetActive(false);
            pool.Add(obj);
        }
    }

    public T GetPooledObject()
    {
        foreach (var obj in pool)
        {
            if (!obj.gameObject.activeInHierarchy)
            {
                obj.gameObject.SetActive(true);
                return obj;
            }
        }

        // If no inactive objects are available, instantiate a new one
        T newObj = GameObject.Instantiate(prefab);
        pool.Add(newObj);
        return newObj;
    }

    public void ReturnToPool(T obj)
    {
        obj.gameObject.SetActive(false);
    }
}

To use this generic pool, you would instantiate it with a specific component type:

public class MyScript : MonoBehaviour
{
    public GameObject myPrefab;
    private ObjectPool<MyComponent> myPool;

    void Start()
    {
        myPool = new ObjectPool<MyComponent>(myPrefab.GetComponent<MyComponent>(), 10);
    }

    void SpawnObject()
    {
        MyComponent obj = myPool.GetPooledObject();
        obj.transform.position = transform.position; // Example usage
    }

    // ...
}

Once retrieved, you can manipulate the object as needed. The following demonstrates setting the object’s position:

Create a free account, or log in.

Gain access to free articles, game development tools, and game assets.