-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathPoolManager.cs
139 lines (124 loc) · 4.34 KB
/
PoolManager.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Wrj
{
public class PoolManager : MonoBehaviour
{
[SerializeField]
[Tooltip("Prototype disabled child object to duplicate in the pool")]
private Component sourceObject = null;
[Tooltip("If the object is not finished within this amount of time it will auto-disable. Set to 0 to for permanence.")]
[SerializeField]
private float defaultLifeSpan = 10f;
public UnityAction<GameObject> OnObjectStashing;
private List<GameObject> _GameObjects = new List<GameObject>();
private Dictionary<GameObject, Coroutine> _RunningTimeouts = new Dictionary<GameObject, Coroutine>();
private void Start()
{
sourceObject.gameObject.SetActive(false);
}
public GameObject Next(float lifeSpan)
{
if (sourceObject == null)
{
Debug.LogWarning($"No source object provided to PoolManager ({name}).", this);
return null;
}
// Get the first available game object from the pool.
// This will add a new one if necessary.
GameObject go = FirstAvailable();
// Start the auto-disable timer, if needed.
if (defaultLifeSpan > 0f)
{
Coroutine thisTimeout = StartCoroutine(LifeSpanRoutine(go, lifeSpan));
_RunningTimeouts.Add(go, thisTimeout);
}
// Position the object to match the source.
go.transform.localPosition = sourceObject.transform.localPosition;
go.transform.localRotation = sourceObject.transform.localRotation;
// Enable in the hierarchy
go.SetActive(true);
return go;
}
public GameObject Next()
{
return Next(defaultLifeSpan);
}
public T Next<T>(float lifeSpan)
{
GameObject go = Next(lifeSpan);
T target = go.GetComponent<T>();
if (target == null) Debug.LogWarning($"Pool element has no {typeof(T).Name}");
return target;
}
public T Next<T>()
{
return Next<T>(defaultLifeSpan);
}
public dynamic NextComponent(float lifeSpan)
{
return Next(lifeSpan).GetComponent(sourceObject.GetType().Name);
}
public dynamic NextComponent()
{
return Next(defaultLifeSpan).GetComponent(sourceObject.GetType().Name);
}
public void Finish(GameObject element)
{
// Find the object in the list
foreach (GameObject go in _GameObjects)
{
if (go == element.gameObject)
{
OnObjectStashing(go);
// Disable it in the hierarchy
go.SetActive(false);
// Kill the auto-disable timer
if (_RunningTimeouts.ContainsKey(go))
{
StopCoroutine(_RunningTimeouts[go]);
_RunningTimeouts.Remove(go);
}
return;
}
}
}
public void Finish(Component element)
{
Finish(element.gameObject);
}
private GameObject FirstAvailable()
{
// Find the first object available
foreach (GameObject go in _GameObjects)
{
if (!go.activeSelf)
{
return go;
}
}
// If none available add a new one
return InstantiateNewObject();
}
private GameObject InstantiateNewObject()
{
// Creat object
GameObject newGO = Instantiate(sourceObject.gameObject);
// Name it
newGO.name = sourceObject.name + "(PoolObject)";
// Child it
newGO.transform.parent = transform;
// Add to list
_GameObjects.Add(newGO);
return newGO;
}
// Auto-disable timer
private IEnumerator LifeSpanRoutine(GameObject go, float lifeSpan)
{
yield return new WaitForSeconds(lifeSpan);
Finish(go);
}
}
}