Skip to content

Instantly share code, notes, and snippets.

@ecmjohnson
Last active June 8, 2021 12:19
Show Gist options
  • Save ecmjohnson/ac0fc5c1160c975551ce16a31c457b28 to your computer and use it in GitHub Desktop.
Save ecmjohnson/ac0fc5c1160c975551ce16a31c457b28 to your computer and use it in GitHub Desktop.
Unity object pooling script
/**
* This class implements the object pool pattern:
*
* It can be used for creating objects exactly as if using Unity's `Instantiate` call. Simply
* call `AcquireObject` with a prefab and an instance of that object will be returned, either
* recycled from the pool or allocated if the pool is empty.
*
* It is the responsibility of the object to set itself inactive with `SetActive(false)` at
* lifetime end. This is how objects are recycled by the pool.
*
* This class also provides the previous `DynamicRegister` functionality. This ensures that all
* GameObjects created during runtime fall under the `_Dynamic` root object. This helps organize
* the scene during debugging.
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public static class ObjectPool
{
/** Public static functions **/
/**
* Returns an object from the pool. Client is responsible for all other initialization.
*/
public static GameObject AcquireObject(GameObject prefab)
{
string key = SanitizeName(prefab.name);
if (!_objects.ContainsKey(key)) {
GenerateObject(prefab);
} else if (_objects[key].Count < 1) {
GenerateObject(prefab);
}
GameObject go = _objects[key].Find(e => !e.activeSelf);
if (go == null) {
go = GenerateObject(prefab);
}
return go;
}
/**
* Returns an object from the pool and sets the provided location and orientation.
*/
public static GameObject AcquireObject(GameObject prefab, Vector2 location, Quaternion quat)
{
GameObject go = AcquireObject(prefab);
go.transform.SetPositionAndRotation(location, quat);
return go;
}
/**
* Adds the requested number of objects to the pool.
*/
public static void AddToPool(GameObject prefab, uint number)
{
for (uint i = 0; i < number; i++) {
GenerateObject(prefab);
}
}
/** Private constants **/
private const string DYNAMIC_NAME = "_Dynamic";
/** Private variables **/
private static Dictionary<string, List<GameObject>> _objects = new Dictionary<string, List<GameObject>>();
private static GameObject _dynamic = null;
/** Private functions **/
private static GameObject GenerateObject(GameObject prefab)
{
GameObject created = GameObject.Instantiate(prefab);
created.SetActive(false);
string key = SanitizeName(created.name);
if (_objects.ContainsKey(key)) {
_objects[key].Add(created);
} else {
List<GameObject> list = new List<GameObject>();
list.Add(created);
_objects.Add(key, list);
}
RegisterDynamic(ref created);
return created;
}
private static void RegisterDynamic(ref GameObject toRegister)
{
if (_dynamic == null) {
_dynamic = GameObject.Find(DYNAMIC_NAME);
if (_dynamic == null) {
_dynamic = new GameObject(DYNAMIC_NAME);
}
}
if (_dynamic != null) {
toRegister.transform.parent = _dynamic.transform;
}
}
private static string SanitizeName(string name)
{
return name.Replace("(Clone)", "");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment