Skip to content

Instantly share code, notes, and snippets.

@DarkStoorM
Last active October 15, 2018 15:26
Show Gist options
  • Save DarkStoorM/e317e834eb6e79c16dc6584017e3fc54 to your computer and use it in GitHub Desktop.
Save DarkStoorM/e317e834eb6e79c16dc6584017e3fc54 to your computer and use it in GitHub Desktop.
Unity Simple Object Pooler
/* Based on Unity Tutorials, a bit modified */
using System.Collections.Generic;
using UnityEngine;
public class ObjectPooler : MonoBehaviour {
[Header("DRAG OBJECT PREFAB HERE")]
/// <summary>
/// Main object, that will be pooled.
/// </summary>
[Tooltip("Main object, that will be pooled.")]
public GameObject pooledObject;
[Header("Parameters")]
/// <summary>
/// Used only to instantiate the maximum amount of objects that player will be allowed to use. This can either be just a maximum number or a number of objects + additional bonus objects
/// </summary>
[Tooltip("Used only to instantiate the maximum amount of objects that player will be allowed to use. This can either be just a maximum number or a number of objects + additional bonus objects")]
public int pooledAmount;
/// <summary>
/// Initializes how many objects will we able to use
/// </summary>
private int maximumPooledAmount;
/// <summary>
/// When true, the pooler will add new objects, expanding the pool instead of returning null
/// </summary>
public bool canExpand;
/// <summary>
/// Maximum allowed number of pooled objects. This allows modifying the maximum number.
/// <para>Use ONLY for modifying the current maximum allowed objects</para>
/// <para>Usage: before grabbing an object by GetPooledObject() - use ObjectPooler.MaximumAllowedObjects = yourNumber;</para>
/// </summary>
public int MaximumAllowedObjects { get; set; }
/// <summary>
/// List of pooled GameObjects
/// </summary>
private List<GameObject> pooledObjects;
/// <summary>
/// Amount of ACTIVE objects only
/// </summary>
private int currentlyActiveObjectsCounter;
private void Awake()
{
maximumPooledAmount = pooledAmount;
// Initialize the maximum amount of objects that we can use
MaximumAllowedObjects = maximumPooledAmount;
// Instantiate the pool of main objects
pooledObjects = new List<GameObject>();
// Initialize the object pool (create new objects)
InstantiateObject(pooledAmount);
}
/// <summary>
/// Expands the Object Pool by Instantiating a new object and adding it into the pool
/// </summary>
public void ExpandPool()
{
// Increase the Pool size
MaximumAllowedObjects++;
// Instantiate and Add new object to the pool
InstantiateObject(1);
}
/// <summary>
/// Returns the first active pooled object
/// </summary>
/// <returns></returns>
public GameObject GetPooledObject()
{
for (int i = 0; i < MaximumAllowedObjects; i++)
{
if(!pooledObjects[i].activeInHierarchy)
{
return pooledObjects[i];
}
}
// Return null as no object is currently active
return null;
}
/// <summary>
/// Returns the current amount of active objects from the pool
/// </summary>
/// <returns></returns>
public int CurrentlyActiveObjects()
{
for (int i = 0; i < pooledObjects.Count; i++)
{
if (!pooledObjects[i].activeInHierarchy)
{
currentlyActiveObjectsCounter++;
}
}
return currentlyActiveObjectsCounter;
}
/// <summary>
/// Returns the entire list of pooled Game Objects
/// </summary>
/// <returns></returns>
public List<GameObject> GetAllObjects() {
return pooledObjects;
}
/// <summary>
/// Returns an available object and expands the pool if needed. Named Spawn for the sake of consistency
/// </summary>
/// <returns></returns>
public GameObject SpawnObject()
{
if (!GetPooledObject())
{
/* There are cases where we should not expand the pool
* For example, when we run out of ammo, we can't add more bullets... */
if (!canExpand)
{
return null;
}
// There was no Object returned, we have to expand the pool by +1 and try again with that object
ExpandPool();
SpawnObject();
}
return GetPooledObject();
}
/// <summary>
/// Instantiates a specific amount of objects and adds them into the pool
/// </summary>
/// <param name="amount">Amount of objects to instantiate</param>
private void InstantiateObject(int amount)
{
for (int i = 0; i < amount; i++)
{
// Instantiate the main object
GameObject obj = Instantiate(pooledObject);
// Move the instantiated object out of the screen to avoid visible spawns
obj.transform.position = new Vector3(999, 999, 999);
// Disable the instantiated main object, so it will be ready to use
obj.SetActive(false);
// Add the instantiated object to the pool
pooledObjects.Add(obj);
}
}
}
@DarkStoorM
Copy link
Author

DarkStoorM commented Oct 14, 2018

Unity Simple Object Pooler version expand compatibility

Based on Unity Tutorials, uploading, because I tend to lose stuff quite often.

  • Add ObjectPooler script to any object, like a global Objects Manager for example
  • Drag a saved prefab
  • Pick a number
  • Allow expanding if you need to find out your max amount
    pooler

All you need is

your_obj = Pooler.SpawnObject();

// Do stuff you need like set position or initial values
if (your_obj) {
    your_obj.SetActive(true);
}

INB4 - Why not static?

This is not a global spawner. I used it as an object spawner for enemies, they had to "spawn" their own objects, so that did not work out.

What about Pool Overflow?

    /// <summary>
    /// Expands the Object Pool by Instantiating a new object and adding it to the pool.
    /// Just in case we try to activate an object, but we don't have any inactive ones in our list
    /// </summary>
    public void ExpandPool()
    {
        // Increase the Pool size
        MaximumAllowedObjects++;

        // Instantiate and Add new object to the pool
        InstantiateObject(1);
    }

Unity version?

I haven't tested it on any version below 2017.2.0b5

An example of "spawning" 20 objects within range of 10 units on XY

using System.Collections;
using UnityEngine;

public class Manager : MonoBehaviour {
    private Vector3 StartingPosition = new Vector3(0,1,0);

    private GameObject PooledObject { get; set; }

    /// <summary>
    /// Main ObjectPooler Component (script)
    /// </summary>
    private ObjectPooler Pooler { get; set; }

    private void Awake()
    {
        // Initialize the Object Pooler
        Pooler = GetComponent<ObjectPooler>();
    }

    private void Start () {
        Spawn();
    }

    private void Spawn()
    {
        for (int i = 0; i < 20; i++)
        {
            SpawnItem();
        }
    }

    private void SpawnItem()
    {
        PooledObject = Pooler.SpawnObject();

        if (PooledObject)
        {
            PooledObject.transform.position = StartingPosition + new Vector3(Random.Range(0,11), 0, Random.Range(0, 11));
            PooledObject.SetActive(true);
        }
        else
        {
            // Pooler was set at 5 objects allowed and canExpand=false
            Debug.Log("No objects were available at this time.");
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment