com.amanotes.prefabpool 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/CHANGELOG.md.meta +7 -0
- package/Docs/PrefabPool-API.md +366 -0
- package/Docs/PrefabPool-API.md.meta +7 -0
- package/Docs.meta +8 -0
- package/README.md +80 -69
- package/Runtime/AssemblyInfo.cs +3 -0
- package/Runtime/AssemblyInfo.cs.meta +11 -0
- package/Runtime/PrefabPool.cs +36 -10
- package/Tests/Runtime/PrefabPool.Test.asmdef +11 -0
- package/Tests/Runtime/PrefabPool.Test.asmdef.meta +7 -0
- package/Tests/Runtime/PrefabPoolGroupTests.cs +224 -0
- package/Tests/Runtime/PrefabPoolGroupTests.cs.meta +11 -0
- package/Tests/Runtime/PrefabPoolLifecycleTests.cs +257 -0
- package/Tests/Runtime/PrefabPoolLifecycleTests.cs.meta +11 -0
- package/Tests/Runtime/PrefabPoolPerformanceTests.cs +212 -0
- package/Tests/Runtime/PrefabPoolPerformanceTests.cs.meta +11 -0
- package/Tests/Runtime/PrefabPoolTestsSetup.cs +14 -0
- package/Tests/Runtime/PrefabPoolTestsSetup.cs.meta +11 -0
- package/Tests/Runtime/TestHelpers/MockPoolPrefab.cs +26 -0
- package/Tests/Runtime/TestHelpers/MockPoolPrefab.cs.meta +11 -0
- package/Tests/Runtime/TestHelpers.meta +8 -0
- package/Tests/Runtime.meta +8 -0
- package/Tests.meta +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.3] - 2026-04-07
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- `PoolEntry.Return`: renamed pooled GameObjects back to their entry `id` in Editor for easier hierarchy debugging (`PrefabPool.cs`)
|
|
7
|
+
|
|
8
|
+
## [1.0.2] - 2026-04-06
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- `PoolEntry.Return`: deactivate GameObject before `SetParent` to prevent `Cannot set the parent of the GameObject while activating or deactivating the parent GameObject` error during scene shutdown
|
|
12
|
+
- `PoolEntry.Get`: explicit `SetActive(true)` to match — objects are now consistently inactive in pool, active when in use
|
|
13
|
+
- `PoolEntry.PreAllocate`: prewarm objects are now spawned inactive, consistent with the return state
|
|
14
|
+
- `PrefabPool.DestroyPool`: `_customPool` (Resize<T>) entries are now properly destroyed on shutdown
|
|
15
|
+
- `PrefabPool.Initialize`: added `_isInitializing` guard to prevent double-prewarm if called concurrently
|
|
16
|
+
- `PoolEntry.PurgeDestroyed`: new method, called on `Register` to remove stale destroyed-object refs when a PoolGroup ScriptableObject is reused across scene loads
|
|
17
|
+
- `PrefabPool.PurgeStaleInstanceMap`: cleans up `_instanceTypeMap` entries for externally-destroyed objects (Editor only)
|
|
18
|
+
|
|
19
|
+
## [1.0.1]
|
|
20
|
+
|
|
21
|
+
- Initial release
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
# PrefabPool API Reference
|
|
2
|
+
|
|
3
|
+
**Package:** `com.amanotes.prefabpool` | **Version:** 1.0.1 | **Namespace:** `Amanotes.Core`
|
|
4
|
+
|
|
5
|
+
Generic object pooling system to eliminate garbage collection spikes from frequent instantiation/destruction.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Interfaces
|
|
10
|
+
|
|
11
|
+
### `IPrefabPool`
|
|
12
|
+
|
|
13
|
+
Main interface for object pool management.
|
|
14
|
+
|
|
15
|
+
```csharp
|
|
16
|
+
public interface IPrefabPool
|
|
17
|
+
{
|
|
18
|
+
bool IsReady { get; } // Pool initialization status
|
|
19
|
+
|
|
20
|
+
void RegisterGroup(PoolGroup group, Transform spawnParent);
|
|
21
|
+
void SetSpawnParent(string groupId, Transform spawnParent);
|
|
22
|
+
GameObject Get(PoolGroup group, string prefabId, Vector3 localPosition = default, Transform customParent = null);
|
|
23
|
+
void Return(PoolGroup group, GameObject gameObject);
|
|
24
|
+
IEnumerator Initialize(); // Pre-allocate pooled objects
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Example:**
|
|
29
|
+
```csharp
|
|
30
|
+
// Setup pool
|
|
31
|
+
var pool = gameObject.AddComponent<PrefabPool>();
|
|
32
|
+
var group = new PoolGroup
|
|
33
|
+
{
|
|
34
|
+
id = "enemies",
|
|
35
|
+
entries = new List<PoolEntry>
|
|
36
|
+
{
|
|
37
|
+
new PoolEntry { id = "basic", prefab = enemyPrefab, prewarmCount = 10 }
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
pool.RegisterGroup(group, transform);
|
|
41
|
+
StartCoroutine(pool.Initialize());
|
|
42
|
+
|
|
43
|
+
// Use pool
|
|
44
|
+
var enemy = pool.Get(group, "basic");
|
|
45
|
+
pool.Return(group, enemy);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### `IPoolPrefab`
|
|
51
|
+
|
|
52
|
+
Lifecycle callback interface for pooled objects.
|
|
53
|
+
|
|
54
|
+
```csharp
|
|
55
|
+
public interface IPoolPrefab
|
|
56
|
+
{
|
|
57
|
+
void OnGet(); // Called when retrieved from pool
|
|
58
|
+
void OnReturn(); // Called when returned to pool
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Implementation:**
|
|
63
|
+
```csharp
|
|
64
|
+
public class PooledTile : MonoBehaviour, IPoolPrefab
|
|
65
|
+
{
|
|
66
|
+
public void OnGet()
|
|
67
|
+
{
|
|
68
|
+
gameObject.SetActive(true);
|
|
69
|
+
ResetState();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public void OnReturn()
|
|
73
|
+
{
|
|
74
|
+
gameObject.SetActive(false);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Core Classes
|
|
82
|
+
|
|
83
|
+
### `PrefabPool`
|
|
84
|
+
|
|
85
|
+
Main implementation of IPrefabPool.
|
|
86
|
+
|
|
87
|
+
```csharp
|
|
88
|
+
public class PrefabPool : MonoBehaviour, IPrefabPool
|
|
89
|
+
{
|
|
90
|
+
public bool IsReady { get; } // True after Initialize() completes
|
|
91
|
+
|
|
92
|
+
public void RegisterGroup(PoolGroup group, Transform spawnParent);
|
|
93
|
+
public void SetSpawnParent(string groupId, Transform spawnParent);
|
|
94
|
+
public GameObject Get(PoolGroup group, string prefabId, Vector3 localPosition = default, Transform customParent = null);
|
|
95
|
+
public void Return(PoolGroup group, GameObject gameObject);
|
|
96
|
+
public IEnumerator Initialize();
|
|
97
|
+
public void Resize<T>(GameObject prefab, List<T> list, int count, Transform parent) where T : Component;
|
|
98
|
+
public void DestroyPool();
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Example:**
|
|
103
|
+
```csharp
|
|
104
|
+
// Dynamic list resizing
|
|
105
|
+
List<Enemy> enemies = new List<Enemy>();
|
|
106
|
+
pool.Resize(enemyPrefab, enemies, 10, transform);
|
|
107
|
+
// enemies.Count == 10
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### `PoolGroup`
|
|
113
|
+
|
|
114
|
+
Organizes related pool entries.
|
|
115
|
+
|
|
116
|
+
```csharp
|
|
117
|
+
[Serializable]
|
|
118
|
+
public class PoolGroup
|
|
119
|
+
{
|
|
120
|
+
public string id; // Group identifier
|
|
121
|
+
public List<PoolEntry> entries; // Pool entries in this group
|
|
122
|
+
public PoolEntry fallbackEntry; // Used when prefabId not found
|
|
123
|
+
public Transform SpawnParent { get; } // Spawn parent transform
|
|
124
|
+
|
|
125
|
+
public GameObject Get(string prefabId, Vector3 localPosition = default, Transform customParent = null);
|
|
126
|
+
public T Get<T>(string prefabId, Vector3 localPosition = default) where T : class;
|
|
127
|
+
public void Return(GameObject gameObject);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Example:**
|
|
132
|
+
```csharp
|
|
133
|
+
// Get with component type
|
|
134
|
+
var enemy = enemyGroup.Get<Enemy>("basic_enemy");
|
|
135
|
+
var handler = tileGroup.Get<IInputHandler>("tile_short");
|
|
136
|
+
|
|
137
|
+
// Fallback entry
|
|
138
|
+
var group = new PoolGroup
|
|
139
|
+
{
|
|
140
|
+
id = "tiles",
|
|
141
|
+
entries = new List<PoolEntry> { /* specific tiles */ },
|
|
142
|
+
fallbackEntry = new PoolEntry { id = "default", prefab = defaultPrefab, prewarmCount = 20 }
|
|
143
|
+
};
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### `PoolEntry`
|
|
149
|
+
|
|
150
|
+
Configuration for single pooled prefab.
|
|
151
|
+
|
|
152
|
+
```csharp
|
|
153
|
+
[Serializable]
|
|
154
|
+
public class PoolEntry
|
|
155
|
+
{
|
|
156
|
+
public string id; // Prefab identifier
|
|
157
|
+
public GameObject prefab; // Prefab to pool
|
|
158
|
+
public int prewarmCount; // Pre-allocate count (0-10)
|
|
159
|
+
|
|
160
|
+
public GameObject Get(Transform poolParent, Transform spawnParent, Vector3 localPosition);
|
|
161
|
+
public void Return(GameObject gameObject, Transform poolParent);
|
|
162
|
+
public void DestroyPool();
|
|
163
|
+
public IEnumerator PreAllocate(Transform poolParent);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Material Pooling
|
|
170
|
+
|
|
171
|
+
### `MaterialPool`
|
|
172
|
+
|
|
173
|
+
Static utility for pooling material instances.
|
|
174
|
+
|
|
175
|
+
```csharp
|
|
176
|
+
public static class MaterialPool
|
|
177
|
+
{
|
|
178
|
+
public static Material Take(Material sourceOrClone, int borrowId);
|
|
179
|
+
public static void Return(int borrowId);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Example:**
|
|
184
|
+
```csharp
|
|
185
|
+
// Borrow material
|
|
186
|
+
Material mat = MaterialPool.Take(originalMaterial, GetInstanceID());
|
|
187
|
+
renderer.material = mat;
|
|
188
|
+
mat.SetAlpha(0.5f);
|
|
189
|
+
|
|
190
|
+
// Return on destroy
|
|
191
|
+
void OnDestroy()
|
|
192
|
+
{
|
|
193
|
+
MaterialPool.Return(GetInstanceID());
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### `MaterialExtensions`
|
|
200
|
+
|
|
201
|
+
Extension methods for material operations.
|
|
202
|
+
|
|
203
|
+
```csharp
|
|
204
|
+
public static class MaterialExtensions
|
|
205
|
+
{
|
|
206
|
+
public static void SetAlpha(this Material m, float a); // Set alpha channel
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Example:**
|
|
211
|
+
```csharp
|
|
212
|
+
material.SetAlpha(0.5f); // 50% transparent
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Extension Methods
|
|
218
|
+
|
|
219
|
+
### `PrefabPoolExtensions`
|
|
220
|
+
|
|
221
|
+
Extension methods for list operations with pooling.
|
|
222
|
+
|
|
223
|
+
```csharp
|
|
224
|
+
public static class PrefabPoolExtensions
|
|
225
|
+
{
|
|
226
|
+
public static void DestroyLast<T>(this List<T> list) where T : Component;
|
|
227
|
+
public static T ClonePrefab<T>(this GameObject prefab, Transform parent) where T : Component;
|
|
228
|
+
public static void ResetAndClear<T>(this List<T> list, GameObject prefab, PrefabPool pool = null) where T : Component;
|
|
229
|
+
public static void Resize<T>(this List<T> list, int count, GameObject prefab, Transform parent, PrefabPool pool) where T : Component;
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Example:**
|
|
234
|
+
```csharp
|
|
235
|
+
// Resize list using pool
|
|
236
|
+
List<Tile> tiles = new List<Tile>();
|
|
237
|
+
tiles.Resize(10, tilePrefab, transform, pool);
|
|
238
|
+
// tiles.Count == 10
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Common Patterns
|
|
244
|
+
|
|
245
|
+
### Pattern 1: Basic Pool Setup
|
|
246
|
+
|
|
247
|
+
```csharp
|
|
248
|
+
// When to use: Standard object pooling
|
|
249
|
+
var pool = gameObject.AddComponent<PrefabPool>();
|
|
250
|
+
|
|
251
|
+
var enemyGroup = new PoolGroup
|
|
252
|
+
{
|
|
253
|
+
id = "enemies",
|
|
254
|
+
entries = new List<PoolEntry>
|
|
255
|
+
{
|
|
256
|
+
new PoolEntry { id = "basic_enemy", prefab = enemyPrefab, prewarmCount = 10 }
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
pool.RegisterGroup(enemyGroup, transform);
|
|
261
|
+
StartCoroutine(pool.Initialize());
|
|
262
|
+
|
|
263
|
+
// Spawn
|
|
264
|
+
var enemy = enemyGroup.Get<Enemy>("basic_enemy");
|
|
265
|
+
|
|
266
|
+
// Despawn
|
|
267
|
+
enemyGroup.Return(enemy.gameObject);
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Pattern 2: Pooled Component with Lifecycle
|
|
271
|
+
|
|
272
|
+
```csharp
|
|
273
|
+
// When to use: Custom initialization/cleanup logic
|
|
274
|
+
public class PooledEnemy : MonoBehaviour, IPoolPrefab
|
|
275
|
+
{
|
|
276
|
+
private Rigidbody rb;
|
|
277
|
+
|
|
278
|
+
void Awake()
|
|
279
|
+
{
|
|
280
|
+
rb = GetComponent<Rigidbody>();
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
public void OnGet()
|
|
284
|
+
{
|
|
285
|
+
gameObject.SetActive(true);
|
|
286
|
+
rb.velocity = Vector3.zero;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
public void OnReturn()
|
|
290
|
+
{
|
|
291
|
+
gameObject.SetActive(false);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Pattern 3: Dynamic List Resizing
|
|
297
|
+
|
|
298
|
+
```csharp
|
|
299
|
+
// When to use: Variable number of active objects
|
|
300
|
+
List<Tile> activeTiles = new List<Tile>();
|
|
301
|
+
|
|
302
|
+
void UpdateTileCount(int count)
|
|
303
|
+
{
|
|
304
|
+
pool.Resize(tilePrefab, activeTiles, count, transform);
|
|
305
|
+
|
|
306
|
+
for (int i = 0; i < activeTiles.Count; i++)
|
|
307
|
+
{
|
|
308
|
+
activeTiles[i].UpdatePosition(i);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Pattern 4: Material Pooling
|
|
314
|
+
|
|
315
|
+
```csharp
|
|
316
|
+
// When to use: Dynamic color/alpha changes without creating material instances
|
|
317
|
+
public class ColoredTile : MonoBehaviour
|
|
318
|
+
{
|
|
319
|
+
private Material instanceMaterial;
|
|
320
|
+
private int borrowId;
|
|
321
|
+
|
|
322
|
+
void Start()
|
|
323
|
+
{
|
|
324
|
+
borrowId = GetInstanceID();
|
|
325
|
+
instanceMaterial = MaterialPool.Take(GetComponent<Renderer>().sharedMaterial, borrowId);
|
|
326
|
+
GetComponent<Renderer>().material = instanceMaterial;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
public void SetColor(Color color)
|
|
330
|
+
{
|
|
331
|
+
instanceMaterial.color = color;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
void OnDestroy()
|
|
335
|
+
{
|
|
336
|
+
MaterialPool.Return(borrowId);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Pattern 5: Fallback Entry
|
|
342
|
+
|
|
343
|
+
```csharp
|
|
344
|
+
// When to use: Default prefab when specific ID not found
|
|
345
|
+
var group = new PoolGroup
|
|
346
|
+
{
|
|
347
|
+
id = "tiles",
|
|
348
|
+
entries = new List<PoolEntry>
|
|
349
|
+
{
|
|
350
|
+
new PoolEntry { id = "special", prefab = specialPrefab, prewarmCount = 5 }
|
|
351
|
+
},
|
|
352
|
+
fallbackEntry = new PoolEntry { id = "default", prefab = defaultPrefab, prewarmCount = 20 }
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Gets special prefab
|
|
356
|
+
var special = group.Get("special");
|
|
357
|
+
|
|
358
|
+
// Gets default prefab (fallback)
|
|
359
|
+
var unknown = group.Get("unknown_id");
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## See Also
|
|
365
|
+
|
|
366
|
+
- [PrefabPool README](../README.md)
|
package/Docs.meta
ADDED
package/README.md
CHANGED
|
@@ -1,105 +1,116 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PrefabPool
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Package:** `com.amanotes.prefabpool`
|
|
4
|
+
**Version:** 1.0.3
|
|
5
|
+
|
|
6
|
+
Generic object pooling system for Unity with lifecycle callbacks and material pooling support.
|
|
7
|
+
|
|
8
|
+
---
|
|
4
9
|
|
|
5
10
|
## Features
|
|
6
11
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
12
|
+
- 🎮 Simple Get/Return API pattern
|
|
13
|
+
- 🎯 Automatic prefab instantiation and reuse
|
|
14
|
+
- 🎨 Lifecycle callbacks via IPoolPrefab interface
|
|
15
|
+
- 🚀 Pre-warming support for performance
|
|
16
|
+
- 🔧 Material pooling for dynamic instances
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Documentation
|
|
21
|
+
|
|
22
|
+
**Complete documentation:** [`Docs/PrefabPool-API.md`](Docs/PrefabPool-API.md)
|
|
23
|
+
|
|
24
|
+
---
|
|
13
25
|
|
|
14
26
|
## Installation
|
|
15
27
|
|
|
16
|
-
Add to your `manifest.json`:
|
|
28
|
+
Add the package to your Unity project via `Packages/manifest.json`:
|
|
29
|
+
|
|
17
30
|
```json
|
|
18
31
|
{
|
|
19
32
|
"dependencies": {
|
|
20
|
-
"com.amanotes.prefabpool": "1.0.
|
|
21
|
-
}
|
|
33
|
+
"com.amanotes.prefabpool": "1.0.3"
|
|
34
|
+
},
|
|
35
|
+
"scopedRegistries": [
|
|
36
|
+
{
|
|
37
|
+
"name": "npmjs",
|
|
38
|
+
"url": "https://registry.npmjs.org/",
|
|
39
|
+
"scopes": [
|
|
40
|
+
"com.amanotes.prefabpool"
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
]
|
|
22
44
|
}
|
|
23
45
|
```
|
|
24
46
|
|
|
47
|
+
---
|
|
48
|
+
|
|
25
49
|
## Quick Start
|
|
26
50
|
|
|
27
51
|
```csharp
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
public class Example : MonoBehaviour
|
|
52
|
+
public class PoolExample : MonoBehaviour
|
|
31
53
|
{
|
|
54
|
+
private PrefabPool pool;
|
|
55
|
+
private PoolGroup enemyGroup;
|
|
56
|
+
|
|
32
57
|
void Start()
|
|
33
58
|
{
|
|
34
|
-
|
|
35
|
-
var group = CreatePoolGroup();
|
|
36
|
-
pool.RegisterGroup(group, transform);
|
|
59
|
+
pool = gameObject.AddComponent<PrefabPool>();
|
|
37
60
|
|
|
38
|
-
|
|
39
|
-
|
|
61
|
+
enemyGroup = new PoolGroup
|
|
62
|
+
{
|
|
63
|
+
id = "enemies",
|
|
64
|
+
entries = new List<PoolEntry>
|
|
65
|
+
{
|
|
66
|
+
new PoolEntry { id = "basic_enemy", prefab = enemyPrefab, prewarmCount = 10 }
|
|
67
|
+
}
|
|
68
|
+
};
|
|
40
69
|
|
|
41
|
-
|
|
42
|
-
pool.
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
## Usage
|
|
48
|
-
|
|
49
|
-
### Implement IPoolPrefab
|
|
50
|
-
|
|
51
|
-
```csharp
|
|
52
|
-
public class Enemy : MonoBehaviour, IPoolPrefab
|
|
53
|
-
{
|
|
54
|
-
public void OnGet()
|
|
55
|
-
{
|
|
56
|
-
// Called when retrieved from pool
|
|
57
|
-
gameObject.SetActive(true);
|
|
58
|
-
ResetState();
|
|
70
|
+
pool.RegisterGroup(enemyGroup, transform);
|
|
71
|
+
StartCoroutine(pool.Initialize());
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
|
|
74
|
+
void SpawnEnemy()
|
|
62
75
|
{
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
var enemy = enemyGroup.Get<Enemy>("basic_enemy");
|
|
77
|
+
enemy.transform.position = GetSpawnPosition();
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
```
|
|
68
81
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```csharp
|
|
72
|
-
var poolGroup = ScriptableObject.CreateInstance<PoolGroup>();
|
|
73
|
-
poolGroup.name = "Enemies";
|
|
74
|
-
poolGroup.entries = new List<PoolEntry>
|
|
75
|
-
{
|
|
76
|
-
new PoolEntry
|
|
77
|
-
{
|
|
78
|
-
id = "enemy",
|
|
79
|
-
prefab = enemyPrefab,
|
|
80
|
-
prewarmCount = 10
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
```
|
|
82
|
+
---
|
|
84
83
|
|
|
85
84
|
## API Reference
|
|
86
85
|
|
|
87
|
-
###
|
|
86
|
+
### Key Classes
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
void Return(GameObject obj);
|
|
93
|
-
IEnumerator Initialize();
|
|
94
|
-
```
|
|
88
|
+
**IPrefabPool**
|
|
89
|
+
- Purpose: Core interface for pool management
|
|
90
|
+
- Key methods: `RegisterGroup()`, `Get()`, `Return()`, `Initialize()`
|
|
95
91
|
|
|
96
|
-
|
|
92
|
+
**PrefabPool**
|
|
93
|
+
- Purpose: Main implementation of IPrefabPool
|
|
94
|
+
- Key methods: `RegisterGroup()`, `Get()`, `Return()`, `Resize<T>()`
|
|
97
95
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
**PoolGroup**
|
|
97
|
+
- Purpose: Organizes related pool entries
|
|
98
|
+
- Key methods: `Get()`, `Get<T>()`, `Return()`
|
|
99
|
+
|
|
100
|
+
**IPoolPrefab**
|
|
101
|
+
- Purpose: Lifecycle callbacks for pooled objects
|
|
102
|
+
- Key methods: `OnGet()`, `OnReturn()`
|
|
103
|
+
|
|
104
|
+
**See:** [Complete API Reference](Docs/PrefabPool-API.md)
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Dependencies
|
|
109
|
+
|
|
110
|
+
- Unity 2022.3+
|
|
111
|
+
|
|
112
|
+
---
|
|
102
113
|
|
|
103
|
-
##
|
|
114
|
+
## Version History
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
See [CHANGELOG.md](CHANGELOG.md)
|