Files
test/Documentation/poolingManager.md
T
2026-05-04 16:16:58 +07:00

75 lines
3.5 KiB
Markdown

# Pooling Manager Execution Flow
## Purpose
The pooling system recycles Addressables-backed `GameObject` instances instead of repeatedly calling `Instantiate` and `Destroy`. Each Addressables key owns one runtime pool that tracks active objects, idle objects, and a memory-release timer.
`PoolManager` loads prefab assets through `AddressableManager`, so it uses the same Addressables initialization path and loaded-prefab cache as the rest of the project. Runtime instances are ordinary instantiated `GameObject`s owned by the pool.
## Runtime Files
- `IPoolable.cs`: prefab-side lifecycle interface.
- `ObjectPool.cs`: owns instances and the loaded prefab reference for one Addressables key.
- `PoolManager.cs`: singleton service used by gameplay, server packet handlers, UI code, and effects systems.
## Spawn Flow
1. Call `PoolManager.Instance.SpawnAsync(...)` or `PoolManager.Instance.Spawn(...)`.
2. `PoolManager` finds or creates an `ObjectPool` for the Addressables key.
3. The pool updates its `memoryReleaseTTL` from the spawn parameter.
4. If a memory release countdown is running, the pool cancels it.
5. The pool reuses an idle object when available.
6. If no idle object exists, the pool waits for `AddressableManager` initialization, loads the prefab with `AddressableManager.LoadPrefabAsync()`, then instantiates it.
7. The instance is parented, positioned, rotated, activated, and all `IPoolable.OnSpawn()` hooks are called.
8. If `autoDespawnTime > 0`, `PoolManager` starts a version-checked auto-despawn coroutine.
9. The spawned `GameObject` is returned to the caller.
## Despawn Flow
1. Call `PoolManager.Instance.Despawn(gameObject)` or `PoolManager.Instance.Despawn(addressableKey, gameObject)`.
2. The target pool validates that the object is currently active.
3. All `IPoolable.OnDespawn()` hooks are called.
4. The object is deactivated, parented under the pool root, and pushed into the idle stack.
5. When the active count reaches zero, the pool starts the memory release countdown.
## Memory Release Flow
1. The countdown waits for the latest `memoryReleaseTTL` value supplied by spawn calls for that key.
2. A new spawn for the same key cancels the countdown and keeps the prefab plus idle instances available.
3. If the countdown completes while active count is still zero, the pool:
- unregisters itself from `PoolManager`;
- destroys all pooled instances;
- calls `AddressableManager.ForceReleaseAsset(addressableKey)` to release the cached prefab asset;
- destroys the pool root object.
## Auto Despawn Safety
Auto despawn stores the instance spawn version when the coroutine starts. If the object is manually despawned and reused before the timer completes, the version changes and the old coroutine will not despawn the new lifecycle.
## Shutdown Flow
`PoolManager` subscribes to `AddressableManager.OnDispose`. When the Addressables manager is disposed, all pools release their instances and prefab assets before `AddressableManager.ReleaseAllAssets()` runs. `PoolManager.OnDestroy()` also releases all pools as a fallback.
## Example
```csharp
GameObject fx = await PoolManager.Instance.SpawnAsync(
"effects/fireball.prefab",
hitPosition,
Quaternion.identity,
memoryReleaseTTL: 15f,
autoDespawnTime: 2f);
```
For coroutine-based callers:
```csharp
PoolManager.Instance.Spawn(
"effects/fireball.prefab",
hitPosition,
Quaternion.identity,
memoryReleaseTTL: 15f,
autoDespawnTime: 2f,
onComplete: spawned => { /* use spawned */ });
```