public class PoolManager : MonoBehaviour {
// Note that because `ObjectPool<T>` is a generic type, we can't use `ObjectPool<T>`
// as the value type of the dictionary, so we cast to `object`.
private Dictionary<Type, object> _pools;
private Dictionary<Type, object> pools {
get {
if (_pools == null) _pools = new Dictionary<Type, object>();
return _pools;
}
}
public void CreatePool<T>(T prefab, Transform parent) where T : Component {
var pool = new ObjectPool<T>(
() => CreateInstance<T>(prefab, parent),
instance => {
instance.gameObject.SetActive(true);
}, instance => {
instance.gameObject.SetActive(false);
}, instance => {
Destroy(instance.gameObject);
}, false, 10, 200);
pools.Add(typeof(T), pool);
}
private ObjectPool<T> GetPool<T>() where T : Component {
if (pools.TryGetValue(typeof(T), out var poolObj)) {
var pool = poolObj as ObjectPool<T>;
return pool;
} else {
return null;
}
}
public T GetInstance<T>() where T : Component {
var pool = GetPool<T>();
if (pool == null) return null;
return pool.Get();
}
public void Release<T>(T instance) where T : Component {
var pool = GetPool<T>();
if (pool == null) Debug.LogWarning($"Tried to release {instance}, but there's no pool of type {typeof(T).Name}");
else pool.Release(instance);
}
private T CreateInstance<T>(T prefab, Transform parent) where T : Component {
T instance = Instantiate(prefab);
instance.transform.SetParent(parent);
instance.gameObject.SetActive(false);
return instance;
}
}
And, at the risk of going overboard on this answer, here's an implementation where pools are mapped by prefab, so you can have different pools for different prefabs with the same type:
public class PoolManager : MonoBehaviour {
// Note that because `ObjectPool<T>` is a generic type, we can't use `ObjectPool<T>`
// as the value type of the dictionary, so we cast to `object`.
private Dictionary<Component, object> _pools;
private Dictionary<Component, object> pools {
get {
if (_pools == null) _pools = new Dictionary<Component, object>();
return _pools;
}
}
public ObjectPool<T> CreatePool<T>(T prefab) where T : Component {
var pool = new ObjectPool<T>(
() => CreateInstance<T>(prefab),
instance => {
instance.gameObject.SetActive(true);
}, instance => {
instance.gameObject.SetActive(false);
}, instance => {
Destroy(instance.gameObject);
}, false, 10, 200);
pools.Add(prefab, pool);
return pool;
}
private ObjectPool<T> GetPool<T>(T prefab) where T : Component {
if (pools.TryGetValue(prefab, out var poolObj)) {
var pool = poolObj as ObjectPool<T>;
return pool;
} else {
return null;
}
}
public T GetInstance<T>(T prefab, Transform parent) where T : Component {
var pool = GetPool<T>(prefab);
if (pool == null) {
pool = CreatePool<T>(prefab);
}
var instance = pool.Get();
if (instance != null) instance.transform.SetParent(parent);
return instance;
}
public void Release<T>(T prefab, T instance) where T : Component {
var pool = GetPool<T>(prefab);
if (pool == null) Debug.LogWarning($"Tried to release {instance}, but there's no pool of type {typeof(T).Name}");
else pool.Release(instance);
}
private T CreateInstance<T>(T prefab) where T : Component {
T instance = Instantiate(prefab);
instance.gameObject.SetActive(false);
return instance;
}
}