3 using System.Collections.Generic;
8 public sealed
class Pool : MonoBehaviour {
9 private bool isPoolContainer;
11 private void Start() {
12 Fiber.Start.Begin.WaitFor(hasReturns).Do(SetParentOnReturn).Again.Finish();
15 private void OnEnable() {
16 if (gameObject.name.EndsWith(
"Pool") || GetComponents<Component>().Length <= 2) {
17 isPoolContainer =
true;
19 DontDestroyOnLoad(target: gameObject);
20 Transform[] children = GetComponentsInChildren<Transform>();
23 for (var i = 1; i < children.Length; ++i) CreatePoolQueue(children[i].gameObject);
25 else if (!queues.ContainsKey(gameObject.name)) {
32 private PoolQueue CreatePoolQueue(GameObject master) {
33 string poolName = $
"{master.name} Pool";
35 if (!queues.ContainsKey(poolName)) {
38 queues[poolName] =
new PoolQueue {Master = master, Parent = master.transform.parent};
39 GameObject poolRoot =
new GameObject(poolName);
40 poolRoot.transform.parent = transform;
41 master.transform.SetParent(poolMonitor.
PoolRoot = poolRoot.transform, worldPositionStays:
false);
42 master.SetActive(
true);
43 return queues[poolName];
51 string name, Vector3 position =
default, Quaternion rotation =
default, Transform parent = default
52 ,
bool enable =
true,
bool poolOnDisable =
true) where T : Component {
53 GameObject clone =
Acquire(name, position, rotation, parent, enable, poolOnDisable);
54 return clone == null ? null : clone.GetComponent<T>();
60 Vector3 position =
default,
61 Quaternion rotation =
default,
62 Transform parent = null,
64 bool poolOnDisable =
true) {
66 if (pool == null)
return null;
73 poolMonitor = clone.gameObject.GetComponent<
PoolMonitor>();
76 if (parent != null) clone.transform.SetParent(parent);
77 clone.transform.position = position;
78 clone.transform.rotation = rotation;
80 clone.gameObject.SetActive(enable);
81 poolMonitor.
InPool =
false;
87 public static void Return(GameObject clone) {
89 if (returns.Count == 1) hasReturns.Fire();
92 private static readonly Fifo<GameObject> returns = Fifo<GameObject>.Instance;
93 private static readonly Emitter hasReturns = Emitter.Instance;
95 private void SetParentOnReturn(Fiber fiber) {
96 while (!returns.Empty) {
97 GameObject clone = returns.Pop();
105 if (clone.transform.parent != poolMonitor.
PoolRoot) clone.transform.SetParent(poolMonitor.
PoolRoot,
false);
108 Debug.LogErrorFormat(
"**** Error: {0} was not created in a pool", clone.name);
111 clone.SetActive(
false);
117 string poolName = $
"{name} Pool";
118 if (queues.ContainsKey(poolName))
return queues[poolName];
120 GameObject gameObject = Objects.Find<GameObject>(name);
122 if (gameObject == null) {
123 gameObject = Resources.Load<GameObject>(name);
125 if (gameObject == null) {
126 Debug.LogErrorFormat(
"Cannot find Prefab or loaded GameObject named '{0}'", name);
132 if (gameObject.scene.name == null) {
133 gameObject = Instantiate(gameObject);
134 gameObject.name = name;
137 var monitor = gameObject.GetComponent<
PoolMonitor>();
138 if (monitor != null)
return queues[poolName] = queues[monitor.MasterName];
140 var queue = (pool ? pool : FindPool()).CreatePoolQueue(gameObject);
141 if (!queues.ContainsKey(name)) queues[name] = queue;
145 private static Pool FindPool() {
147 var anyMonitor = FindObjectOfType<PoolMonitor>();
149 if (anyMonitor != null) pool = anyMonitor.GetComponentInParent<
Pool>();
152 var pools = FindObjectsOfType<Pool>();
154 for (var i = 0; i < pools.Length && pool == null; i++) {
155 if (pools[i].isPoolContainer) pool = pools[i];
159 if (pool == null) pool = Components.Create<Pool>(
"Pool");
163 private sealed
class PoolDict : Dictionary<string, PoolQueue> { }
165 private static readonly PoolDict queues =
new PoolDict();
185 clone = Instantiate(
Master);
186 clone.name = $
"{Master.name} (clone {++count})";
189 clone.transform.SetParent(
Parent);
MonoBehaviour to provide pooling functionality for child GameObjects. To be eligible they must be cre...
static T Acquire< T >(string name, Vector3 position=default, Quaternion rotation=default, Transform parent=default, bool enable=true, bool poolOnDisable=true)
Use Pool.Acquire<T>() to get a reference to a cloned gameObject instead of Instantiate<T>(). All parameters bar name are optional.
static PoolQueue PoolFor(string name, Pool pool=null)
Retrieve a reference to the pooling queue for the GameObject named
Each GameObject enabled for pooling resides in a PoolQueue.
GameObject Master
Master GameObject from which copies are cloned
static void Return(GameObject clone)
Give an object created by Acquire in any pool, return it to the pool for reuse. Only needed if poolOn...
static GameObject Acquire(string name, Vector3 position=default, Quaternion rotation=default, Transform parent=null, bool enable=true, bool poolOnDisable=true)
Use Pool.Acquire() to get a reference to a cloned gameObject instead of Instantiate(). All parameters bar name are optional.
GameObject Fetch()
Fetch a cloned GameObject - either from a list of those returned or instantiating a new instance ...