Skip to content

Commit bbd1356

Browse files
committed
PoolGameObject Self Clear on Empty
1 parent 7335da3 commit bbd1356

File tree

11 files changed

+124
-68
lines changed

11 files changed

+124
-68
lines changed

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/Foundation/Pools/AssetRefGameObjectItemPool.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,25 @@
22
using UnityEngine;
33
using ZBase.Foundation.Pooling.AddressableAssets;
44

5-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool
5+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool
66
{
77
public class AssetRefGameObjectItemPool : AssetRefGameObjectPool
88
{
9-
internal event Action<UnityEngine.GameObject> OnReturn;
9+
internal event Action<GameObject> OnReturn;
1010

1111
public AssetRefGameObjectItemPool(AssetRefGameObjectPrefab prefab) : base(prefab)
1212
{
1313
}
1414

15-
protected override void ProcessNewInstance(UnityEngine.GameObject instance)
15+
protected override void ProcessNewInstance(GameObject instance)
1616
{
1717
base.ProcessNewInstance(instance);
1818
if (!instance.TryGetComponent<AssetRefGameObjectPoolItem>(out var poolItem))
1919
poolItem = instance.AddComponent<AssetRefGameObjectPoolItem>();
2020
poolItem.SetUp(this, instance, Prefab);
2121
}
2222

23-
protected override void ReturnPreprocess(UnityEngine.GameObject instance)
23+
protected override void ReturnPreprocess(GameObject instance)
2424
{
2525
base.ReturnPreprocess(instance);
2626
OnReturn?.Invoke(instance);

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/Foundation/Pools/GameObjectItemPool.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,38 @@
11
using System;
2+
using System.Collections.Generic;
3+
using UnityEngine;
24
using ZBase.Foundation.Pooling.UnityPools;
35

4-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool
6+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool
57
{
68
public sealed class GameObjectItemPool : GameObjectPool
79
{
8-
internal event Action<UnityEngine.GameObject> OnReturn;
9-
10-
public GameObjectItemPool(GameObjectPrefab prefab) : base(prefab)
11-
{
12-
}
10+
internal event Action<GameObject> OnReturn;
11+
internal event Action<GameObjectItemPool> OnPoolEmpty;
12+
private readonly List<int > _poolItems = new();
13+
14+
internal int ID { get; }
15+
16+
public GameObjectItemPool(GameObjectPrefab prefab) : base(prefab) => ID = Prefab.Source.GetInstanceID();
1317

14-
protected override void ProcessNewInstance(UnityEngine.GameObject instance)
18+
protected override void ProcessNewInstance(GameObject instance)
1519
{
1620
base.ProcessNewInstance(instance);
1721
if (!instance.TryGetComponent<GameObjectPoolItem>(out var poolItem))
1822
poolItem = instance.AddComponent<GameObjectPoolItem>();
1923
poolItem.SetUp(this, instance, Prefab);
24+
poolItem.OnItemDestroy += OnItemDestroy;
25+
this._poolItems.Add(instance.GetInstanceID());
2026
}
2127

22-
protected override void ReturnPreprocess(UnityEngine.GameObject instance)
28+
private void OnItemDestroy(GameObject instance)
29+
{
30+
this._poolItems.Remove(instance.GetInstanceID());
31+
if(this._poolItems.Count == 0)
32+
OnPoolEmpty?.Invoke(this);
33+
}
34+
35+
protected override void ReturnPreprocess(GameObject instance)
2336
{
2437
base.ReturnPreprocess(instance);
2538
OnReturn?.Invoke(instance);

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/GlobalPools/Extensions/LazyAssetRefGameObjectPool.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,26 @@
33
using UnityEngine.AddressableAssets;
44
using ZBase.Foundation.Pooling.AddressableAssets;
55

6-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool.Extensions
6+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool.Extensions
77
{
88

99
public static class LazyAssetRefGameObjectPool
1010
{
1111
private static GlobalAssetRefGameObjectPool GlobalGameObjectPool => SharedPool.Of<GlobalAssetRefGameObjectPool>();
1212

13-
public static async UniTask<UnityEngine.GameObject> Rent(AssetReferenceGameObject gameObjectReference)
13+
public static async UniTask<GameObject> Rent(AssetReferenceGameObject gameObjectReference)
1414
=> await GlobalGameObjectPool.Rent(gameObjectReference);
1515

16-
public static async UniTask<UnityEngine.GameObject> Rent(AssetRefGameObjectPrefab gameObjectReference)
16+
public static async UniTask<GameObject> Rent(AssetRefGameObjectPrefab gameObjectReference)
1717
=> await GlobalGameObjectPool.Rent(gameObjectReference);
1818

19-
public static void Return(UnityEngine.GameObject gameObject)
19+
public static void Return(GameObject gameObject)
2020
=> GlobalGameObjectPool.Return(gameObject);
2121

22-
public static void Return(AssetRefGameObjectPrefab gameObjectReference, UnityEngine.GameObject gameObject)
22+
public static void Return(AssetRefGameObjectPrefab gameObjectReference, GameObject gameObject)
2323
=> GlobalGameObjectPool.Return(gameObjectReference, gameObject);
2424

25-
public static void ReleaseInstances(int keep, System.Action<UnityEngine.GameObject> onReleased = null)
25+
public static void ReleaseInstances(int keep, System.Action<GameObject> onReleased = null)
2626
=> GlobalGameObjectPool.ReleaseInstances(keep, onReleased);
2727

2828
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/GlobalPools/Extensions/LazyGameObjectPool.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22
using UnityEngine;
33
using ZBase.Foundation.Pooling.UnityPools;
44

5-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool.Extensions
5+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool.Extensions
66
{
77

88
public static class LazyGameObjectPool
99
{
1010
private static GlobalGameObjectPool GlobalGameObjectPool => SharedPool.Of<GlobalGameObjectPool>();
1111

12-
public static async UniTask<UnityEngine.GameObject> Rent(UnityEngine.GameObject gameObjectReference)
12+
public static async UniTask<GameObject> Rent(GameObject gameObjectReference)
1313
=> await GlobalGameObjectPool.Rent(gameObjectReference);
14-
public static async UniTask<UnityEngine.GameObject> Rent(GameObjectPrefab gameObjectReference)
14+
public static async UniTask<GameObject> Rent(GameObjectPrefab gameObjectReference)
1515
=> await GlobalGameObjectPool.Rent(gameObjectReference);
16-
public static void Return(UnityEngine.GameObject gameObject)
16+
public static void Return(GameObject gameObject)
1717
=> GlobalGameObjectPool.Return(gameObject);
1818

19-
public static void Return(GameObjectPrefab gameObjectReference, UnityEngine.GameObject gameObject)
19+
public static void Return(GameObjectPrefab gameObjectReference, GameObject gameObject)
2020
=> GlobalGameObjectPool.Return(gameObjectReference, gameObject);
2121

22-
public static void ReleaseInstances(int keep, System.Action<UnityEngine.GameObject> onReleased = null)
22+
public static void ReleaseInstances(int keep, System.Action<GameObject> onReleased = null)
2323
=> GlobalGameObjectPool.ReleaseInstances(keep, onReleased);
2424

2525
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/GlobalPools/GlobalAssetRefGameObjectPool.cs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,77 @@
55
using UnityEngine.AddressableAssets;
66
using ZBase.Foundation.Pooling.AddressableAssets;
77

8-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool
8+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool
99
{
1010
public class GlobalAssetRefGameObjectPool : IPool, IShareable
1111
{
1212
private readonly Dictionary<AssetRefGameObjectPrefab, AssetRefGameObjectItemPool> _pools =
1313
new(new AssetRefGameObjectPrefabEqualityComparer());
1414

15-
private readonly Dictionary<int, AssetRefGameObjectPrefab> _prefabToAssetReference = new();
15+
private readonly Dictionary<int, AssetRefGameObjectItemPool> _dicTrackingInstancePools = new();
1616

1717
private readonly Dictionary<AssetReferenceGameObject, AssetRefGameObjectPrefab> _poolKeyCache = new();
1818

19-
public async UniTask<UnityEngine.GameObject> Rent(AssetReferenceGameObject gameObjectReference)
19+
public async UniTask<GameObject> Rent(AssetReferenceGameObject gameObjectReference)
2020
{
2121
if (!_poolKeyCache.TryGetValue(gameObjectReference, out var key))
2222
_poolKeyCache.Add(gameObjectReference,
2323
key = new AssetRefGameObjectPrefab { Source = gameObjectReference, });
2424
return await Rent(key);
2525
}
2626

27-
public async UniTask<UnityEngine.GameObject> Rent(AssetRefGameObjectPrefab gameObjectReference)
27+
public async UniTask<GameObject> Rent(AssetRefGameObjectPrefab gameObjectReference)
2828
{
2929
if (!_pools.TryGetValue(gameObjectReference, out var pool))
3030
{
3131
pool = new AssetRefGameObjectItemPool(gameObjectReference);
3232
pool.OnReturn += OnReturnToPool;
3333
this._pools.Add(gameObjectReference, pool);
3434
}
35-
UnityEngine.GameObject item = await pool.Rent();
36-
_prefabToAssetReference.Add(item.GetInstanceID(), gameObjectReference);
35+
GameObject item = await pool.Rent();
36+
_dicTrackingInstancePools.Add(item.GetInstanceID(), pool);
3737
return item;
3838
}
3939

40-
public void Return(UnityEngine.GameObject gameObject)
40+
public void Return(GameObject gameObject)
4141
{
4242
if (!gameObject)
4343
return;
44-
if (_prefabToAssetReference.TryGetValue(gameObject.GetInstanceID(), out var assetReference))
45-
Return(assetReference, gameObject);
44+
if (_dicTrackingInstancePools.TryGetValue(gameObject.GetInstanceID(), out var pool))
45+
pool.Return(gameObject);
4646
else
47-
Debug.LogError($"GameObject {gameObject.name} is not registered in the pool or was already returned.");
47+
Debug.LogWarning($"GameObject {gameObject.name} is not registered in the pool or was already returned.");
4848
}
4949

50-
public void Return(AssetRefGameObjectPrefab gameObjectReference, UnityEngine.GameObject gameObject)
50+
public void Return(AssetRefGameObjectPrefab gameObjectReference, GameObject gameObject)
5151
{
5252
if (_pools.TryGetValue(gameObjectReference, out var pool))
5353
pool.Return(gameObject);
5454
}
5555

56-
public void ReleaseInstances(int keep, System.Action<UnityEngine.GameObject> onReleased = null)
56+
public void ReleaseInstances(int keep, System.Action<GameObject> onReleased = null)
5757
{
5858
foreach (var pool in _pools.Values)
5959
pool.ReleaseInstances(keep, onReleased);
6060
}
6161

62-
private void OnReturnToPool(UnityEngine.GameObject gameObject) => _prefabToAssetReference.Remove(gameObject.GetInstanceID());
62+
private void OnReturnToPool(GameObject gameObject) => _dicTrackingInstancePools.Remove(gameObject.GetInstanceID());
6363

64-
private class AssetRefGameObjectPrefabEqualityComparer : IEqualityComparer<AssetRefGameObjectPrefab>
65-
{
66-
public bool Equals([NotNull] AssetRefGameObjectPrefab x, [NotNull] AssetRefGameObjectPrefab y)
67-
=> y is { Source: not null } && x is { Source: not null } &&
68-
x.Source.AssetGUID.Equals(y.Source.AssetGUID);
69-
public int GetHashCode(AssetRefGameObjectPrefab obj) => obj.Source.AssetGUID.GetHashCode();
70-
}
71-
7264
public void Dispose()
7365
{
7466
foreach (var pool in _pools.Values)
7567
pool.Dispose();
7668
_pools.Clear();
77-
_prefabToAssetReference.Clear();
69+
_dicTrackingInstancePools.Clear();
7870
_poolKeyCache.Clear();
7971
}
72+
73+
private class AssetRefGameObjectPrefabEqualityComparer : IEqualityComparer<AssetRefGameObjectPrefab>
74+
{
75+
public bool Equals([NotNull] AssetRefGameObjectPrefab x, [NotNull] AssetRefGameObjectPrefab y)
76+
=> y is { Source: not null } && x is { Source: not null } &&
77+
x.Source.AssetGUID.Equals(y.Source.AssetGUID);
78+
public int GetHashCode(AssetRefGameObjectPrefab obj) => obj.Source.AssetGUID.GetHashCode();
79+
}
8080
}
8181
}

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/GlobalPools/GlobalGameObjectPool.cs

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@
44
using UnityEngine;
55
using ZBase.Foundation.Pooling.UnityPools;
66

7-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool
7+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool
88
{
99
public class GlobalGameObjectPool : IPool, IShareable
1010
{
1111
private readonly Dictionary<int, GameObjectItemPool> _pools = new();
12-
private readonly Dictionary<int, GameObjectPrefab> _prefabToAssetReference = new();
12+
private readonly Dictionary<int, GameObjectItemPool> _dicTrackingInstancePools = new();
1313
private readonly Dictionary<int, GameObjectPrefab> _poolKeyCache = new();
1414

15-
public async UniTask<UnityEngine.GameObject> Rent(UnityEngine.GameObject gameObjectReference)
15+
public async UniTask<GameObject> Rent(GameObject gameObjectReference)
1616
{
1717
var hash = gameObjectReference.GetInstanceID();
1818
if (!_poolKeyCache.TryGetValue(hash, out var key))
1919
this._poolKeyCache.Add(hash, key = new GameObjectPrefab { Source = gameObjectReference });
2020
return await Rent(key);
2121
}
2222

23-
public async UniTask<UnityEngine.GameObject> Rent(GameObjectPrefab gameObjectReference)
23+
public async UniTask<GameObject> Rent(GameObjectPrefab gameObjectReference)
2424
{
2525
var instanceID = gameObjectReference.Source.GetInstanceID();
2626
if (!_pools.TryGetValue(instanceID, out var pool))
@@ -29,44 +29,78 @@ public class GlobalGameObjectPool : IPool, IShareable
2929
throw new Exception($"Non Prefab not supported {gameObjectReference.Source.name}");
3030
pool = new GameObjectItemPool(gameObjectReference);
3131
pool.OnReturn += OnReturnToPool;
32+
pool.OnPoolEmpty += OnPoolEmpty;
3233
this._pools.Add(instanceID, pool);
3334
}
3435

35-
UnityEngine.GameObject item = await pool.Rent();
36-
_prefabToAssetReference.Add(item.GetInstanceID(), gameObjectReference);
36+
GameObject item = await pool.Rent();
37+
this._dicTrackingInstancePools.Add(item.GetInstanceID(), pool);
3738
return item;
3839
}
3940

40-
public void Return(UnityEngine.GameObject gameObject)
41+
public void Return(GameObject gameObject)
4142
{
4243
if (!gameObject)
4344
return;
44-
if (_prefabToAssetReference.TryGetValue(gameObject.GetInstanceID(), out var assetReference))
45-
Return(assetReference, gameObject);
45+
if (this._dicTrackingInstancePools.TryGetValue(gameObject.GetInstanceID(), out var pool))
46+
pool.Return(gameObject);
4647
else
47-
Debug.LogWarning($"GameObject {gameObject.name} is not registered in the pool or was already returned.");
48+
Debug.LogWarning(
49+
$"GameObject {gameObject.name} is not registered in the pool or was already returned.");
4850
}
4951

50-
public void Return(GameObjectPrefab gameObjectReference, UnityEngine.GameObject gameObject)
52+
public void Return(GameObjectPrefab gameObjectReference, GameObject gameObject)
5153
{
5254
if (_pools.TryGetValue(gameObjectReference.Source.GetInstanceID(), out var pool))
5355
pool.Return(gameObject);
5456
}
5557

56-
public void ReleaseInstances(int keep, Action<UnityEngine.GameObject> onReleased = null)
58+
public void ReleaseInstances(int keep, Action<GameObject> onReleased = null)
5759
{
5860
foreach (var pool in _pools.Values)
5961
pool.ReleaseInstances(keep, onReleased);
6062
}
6163

62-
private void OnReturnToPool(UnityEngine.GameObject gameObject) => _prefabToAssetReference.Remove(gameObject.GetInstanceID());
64+
private void OnPoolEmpty(GameObjectItemPool pool)
65+
{
66+
pool.Dispose();
67+
this._pools.Remove(pool.ID);
68+
RemoveReference(pool.ID);
69+
RemoveCacheKey(pool.ID);
70+
}
6371

72+
private void RemoveReference(int poolID)
73+
{
74+
foreach (var keyPair in this._dicTrackingInstancePools)
75+
{
76+
if (keyPair.Value.ID != poolID)
77+
continue;
78+
this._dicTrackingInstancePools.Remove(keyPair.Key);
79+
Debug.LogWarning($"Pool {poolID} is empty and removed from tracking");
80+
break;
81+
}
82+
}
83+
84+
private void RemoveCacheKey(int poolID)
85+
{
86+
foreach (var keyPair in _poolKeyCache)
87+
{
88+
if (keyPair.Value.Source.GetInstanceID() != poolID)
89+
continue;
90+
this._poolKeyCache.Remove(keyPair.Key);
91+
break;
92+
}
93+
}
94+
95+
private void OnReturnToPool(GameObject gameObject) =>
96+
this._dicTrackingInstancePools.Remove(gameObject.GetInstanceID());
97+
6498
public void Dispose()
6599
{
66100
foreach (var pool in _pools.Values)
67101
pool.Dispose();
68102
_pools.Clear();
69-
_prefabToAssetReference.Clear();
103+
_dicTrackingInstancePools.Clear();
70104
_poolKeyCache.Clear();
71105
}
72106
}

Packages/ZBase.Foundation.Pooling/GameObjectLazyPool/Items/AssetRefGameObjectPoolItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using ZBase.Foundation.Pooling.AddressableAssets;
22

3-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool
3+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool
44
{
55
public class AssetRefGameObjectPoolItem : PoolItem<UnityEngine.GameObject, AssetRefGameObjectPrefab>
66
{
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
using ZBase.Foundation.Pooling.UnityPools;
2-
namespace ZBase.Foundation.Pooling.GameObject.LazyPool
1+
using System;
2+
using UnityEngine;
3+
using ZBase.Foundation.Pooling.UnityPools;
4+
namespace ZBase.Foundation.Pooling.GameObjectItem.LazyPool
35
{
4-
public class GameObjectPoolItem : PoolItem<UnityEngine.GameObject, GameObjectPrefab>
6+
public class GameObjectPoolItem : PoolItem<GameObject, GameObjectPrefab>
57
{
8+
public event Action<GameObject> OnItemDestroy;
9+
10+
protected override void OnDestroy()
11+
{
12+
base.OnDestroy();
13+
this.OnItemDestroy?.Invoke(this.gameObject);
14+
}
615
}
716
}

0 commit comments

Comments
 (0)