-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathObjectPool.cs
More file actions
168 lines (130 loc) · 4.69 KB
/
ObjectPool.cs
File metadata and controls
168 lines (130 loc) · 4.69 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
using System;
using System.Collections;
using System.Collections.Generic;
using Gruel.CoroutineUtils;
using Gruel.ResourceManagement;
using UnityEngine;
namespace Gruel.ObjectPool {
public class ObjectPool : MonoBehaviour {
#region Properties
#endregion Properties
#region Fields
[SerializeField] private Transform _poolContainer;
private static Dictionary<int, List<IPoolable>> _poolComplete;
private static Dictionary<int, Queue<IPoolable>> _poolAvailable;
private static Dictionary<int, List<IPoolable>> _poolCheckedOut;
private static Dictionary<int, string> _paths;
private static ObjectPool _instance;
#endregion Fields
#region Public Methods
public void Init() {
// Setup instance.
if (_instance != null) {
Debug.LogError("ObjectPool: There is already an instance of ObjectPool!");
Destroy(gameObject);
} else {
_instance = this;
}
_poolComplete = new Dictionary<int, List<IPoolable>>();
_poolAvailable = new Dictionary<int, Queue<IPoolable>>();
_poolCheckedOut = new Dictionary<int, List<IPoolable>>();
_paths = new Dictionary<int, string>();
}
public static Coroutine Add(string path, int amount) {
Debug.Log($"ObjectPool.Add: Adding {amount} {path}");
return CoroutineRunner.StartCoroutine(_instance.AddCor(path, amount));
}
public static void Remove(int hash) {
if (_poolAvailable.ContainsKey(hash) == false) {
Debug.LogError($"ObjectPool.Remove: This hash does not exist in the pool!");
return;
}
// Destroy all poolable objects of this type.
var list = _poolComplete[hash];
for (int i = 0, n = list.Count; i < n; i++) {
list[i]?.Destroy();
}
// Remove this hash from the dictionaries.
_poolComplete.Remove(hash);
_poolAvailable.Remove(hash);
_poolCheckedOut.Remove(hash);
_paths.Remove(hash);
}
public static IPoolable Get(int hash) {
if (_poolAvailable.ContainsKey(hash) == false) {
Debug.LogError($"ObjectPool.Get: This hash does not exist in the pool!");
return null;
}
if (_poolAvailable[hash].Count < 1) {
Debug.LogWarning($"ObjectPool.Get: Not enough \"{_paths[hash]}\" objects in pool! Adding another non-async");
_instance.AddNonAsync(hash);
}
// Remove poolable from available queue.
var poolable = _poolAvailable[hash].Dequeue();
// Add poolable to the checked out list.
_poolCheckedOut[hash].Add(poolable);
// Tell the poolable to unpool
poolable.Unpool();
// Return poolable to caller.
return poolable;
}
public static void Repool(IPoolable poolable) {
// Get poolable hash.
var hash = poolable.Hash;
// Tell poolable to pool itself.
poolable.Pool();
// Remove from the checkedout list.
_poolCheckedOut[hash].Remove(poolable);
// Add to the available queue.
_poolAvailable[hash].Enqueue(poolable);
}
#endregion Public Methods
#region Private Methods
private IEnumerator AddCor(string path, int amount) {
// Get path hash.
var hash = path.GetHashCode();
// Save path, we may need it again in the future.
_paths.Add(hash, path);
// Create new queue/list in dictionaries if one doesn't already exist.
if (_poolComplete.ContainsKey(hash) == false) {
_poolComplete.Add(hash, new List<IPoolable>());
_poolAvailable.Add(hash, new Queue<IPoolable>());
_poolCheckedOut.Add(hash, new List<IPoolable>());
}
// Load resource.
UnityEngine.Object loadedObject = null;
Action<UnityEngine.Object> onResourceLoaded = delegate(UnityEngine.Object o) {
loadedObject = o;
};
yield return AsyncLoader.LoadResource(path, onLoaded: onResourceLoaded);
// Instantiate objects and add to dictionary.
for (int i = 0; i < amount; i++) {
// Instantiate object using loaded resource.
var instantiatedObject = (GameObject)Instantiate(loadedObject, _poolContainer);
// Get the poolable interface.
var poolable = instantiatedObject.GetComponent<IPoolable>();
// Save hash in the poolable.
poolable.Hash = hash;
// Tell the poolable its being pooled.
poolable.Pool();
// Add to lists/queues.
_poolComplete[hash].Add(poolable);
_poolAvailable[hash].Enqueue(poolable);
}
}
private void AddNonAsync(int hash) {
// Load and instantiate the object.
var instantiatedObject = (GameObject)Instantiate(Resources.Load(_paths[hash]), _poolContainer);
// Get the poolable interface.
var poolable = instantiatedObject.GetComponent<IPoolable>();
// Save hash in the poolable.
poolable.Hash = hash;
// Tell the poolable its being pooled.
poolable.Pool();
// Add to lists/queues.
_poolComplete[hash].Add(poolable);
_poolAvailable[hash].Enqueue(poolable);
}
#endregion Private Methods
}
}