Skip to content

Instantly share code, notes, and snippets.

@shane-harper
Last active January 2, 2021 03:05
Show Gist options
  • Save shane-harper/ca272eff435bfcbafd95ed382a29de66 to your computer and use it in GitHub Desktop.
Save shane-harper/ca272eff435bfcbafd95ed382a29de66 to your computer and use it in GitHub Desktop.
A generic C# pool class and example PrefabPool class for use with Unity3D prefabs
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;
/// <summary>
/// A strongly typed pool of objects. When the pool is empty, new instances will be created when requested
/// </summary>
/// <typeparam name="T">The type of elements in the pool</typeparam>
public abstract class Pool<T>
{
protected readonly T Original;
/// <summary>
/// Create new pool
/// </summary>
/// <param name="original">Original asset</param>
/// <param name="capacity">The initial number of elements that the pool can contain.</param>
protected Pool(T original, int capacity = 0)
{
Original = original;
_queue = new Queue<T>(capacity);
}
/// <summary>
/// Create a new item instance
/// </summary>
/// <remarks>Called when no items are available in the queue</remarks>
protected abstract T CreateNewInstance();
/// <summary>
/// Get an item from the pool or create a new one if none is available
/// </summary>
/// <returns>Returns a copy of the original asset</returns>
public virtual T Get()
{
return _queue.Count > 0 ? _queue.Dequeue() : CreateNewInstance();
}
/// <summary>
/// Get an item from the pool or create a new one if none is available
/// </summary>
/// <param name="isNew">Returns true if the returned asset has just been created</param>
/// <returns>Returns a copy of the original asset</returns>
public virtual T Get(out bool isNew)
{
if (_queue.Count > 0)
{
isNew = false;
return _queue.Dequeue();
}
isNew = true;
return CreateNewInstance();
}
/// <summary>
/// Return item to the pool
/// </summary>
/// <param name="item">Item to be returned to the pool</param>
public virtual void Return(T item)
{
_queue.Enqueue(item);
}
#region Queue
/// <summary>
/// Number of items currently queued in the pool
/// </summary>
public int Count
{
get { return _queue.Count; }
}
private readonly Queue<T> _queue;
#endregion
}
/// <inheritdoc />
public class PrefabPool<T> : Pool<T> where T : MonoBehaviour
{
/// <summary>
/// Parent Transform to create new instances under
/// </summary>
public Transform Parent;
public PrefabPool(T original, int capacity = 0) : base(original, capacity)
{
}
/// <inheritdoc />
protected override T CreateNewInstance()
{
return Object.Instantiate(Original, Parent);
}
}
@shane-harper
Copy link
Author

I removed auto tracking as it seemed like an over-complication.

I added an alternate Get method that will tell you if the item you've just retrieved is new. This can be helpful when initializing new items as they are created.

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