diff --git a/Assets/Framework/Scripts/Infra.meta b/Assets/Framework/Scripts/Infra.meta new file mode 100644 index 0000000..6befd63 --- /dev/null +++ b/Assets/Framework/Scripts/Infra.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cfdbe50b7b8b9b142bff6b665fa12380 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/GameObjectPool.cs b/Assets/Framework/Scripts/Utilities/ObjectPool/GameObjectPool.cs new file mode 100644 index 0000000..78693e6 --- /dev/null +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/GameObjectPool.cs @@ -0,0 +1,72 @@ +using UnityEngine; +using UnityEngine.Pool; +using System.Collections; + +namespace Framework.Utilities.ObjectPool +{ + public class GameobjectPool : IObjectPool + { + private readonly ObjectPool _pool; + private readonly Transform _parent; + private readonly GameObject _prefab; + private readonly int _initializedSize; + private readonly int _maxSize; + + public int InitializedSize => _initializedSize; + + public int MaxSize => _maxSize; + + /// + /// 仅提供预制体和父节点 + /// + /// + /// + /// + /// + public GameobjectPool(Transform parent, GameObject prefab, int initializedSize, int maxSize) + { + _parent = parent; + _prefab = prefab; + _initializedSize = initializedSize; + _maxSize = maxSize; + + _pool = new ObjectPool( + createFunc: () => Object.Instantiate(_prefab, _parent), + actionOnGet: go => { if (go != null) go.SetActive(true); }, + actionOnRelease: go => { if (go != null) { go.SetActive(false); go.transform.SetParent(_parent); } }, + actionOnDestroy: obj => { if (obj != null) Object.Destroy(obj); }, + collectionCheck: false, + defaultCapacity: initializedSize, + maxSize: maxSize + ); + } + + public GameObject Create() + { + return _pool.Get(); + } + + public void Clear() + { + _pool.Clear(); + } + + public void Destroy(GameObject obj) + { + if (obj != null) + Object.Destroy(obj); + } + + public GameObject Get() + { + return _pool.Get(); + } + + // NOTE: 实现一个回调函数, 实现 After Get + + public void Release(GameObject obj) + { + _pool.Release(obj); + } + } +} \ No newline at end of file diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/GameObjectPool.cs.meta b/Assets/Framework/Scripts/Utilities/ObjectPool/GameObjectPool.cs.meta new file mode 100644 index 0000000..6d32e80 --- /dev/null +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/GameObjectPool.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 375a961710c485e49b359298b09e1380 \ No newline at end of file diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/IObjectPool.cs b/Assets/Framework/Scripts/Utilities/ObjectPool/IObjectPool.cs index 679d1d2..4d12f1d 100644 --- a/Assets/Framework/Scripts/Utilities/ObjectPool/IObjectPool.cs +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/IObjectPool.cs @@ -2,8 +2,13 @@ namespace Framework.Utilities.ObjectPool { public interface IObjectPool { + int InitializedSize { get; } + int MaxSize { get; } + T Get(); + T Create(); void Release(T obj); + void Destroy(T obj); void Clear(); } } \ No newline at end of file diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/IPoolManager.cs b/Assets/Framework/Scripts/Utilities/ObjectPool/IPoolManager.cs new file mode 100644 index 0000000..aa14db4 --- /dev/null +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/IPoolManager.cs @@ -0,0 +1,14 @@ +using UnityEngine; + +namespace Framework.Utilities.ObjectPool +{ + /// + /// 工厂方法, 用于管理所有的对象池 + /// + public interface IPoolManager + { + IObjectPool GetPool(string key = null) where T : class; + IObjectPool CreatePool(string key, IObjectPool pool); + bool TryRelease(T item) where T : class; + } +} \ No newline at end of file diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/IPoolManager.cs.meta b/Assets/Framework/Scripts/Utilities/ObjectPool/IPoolManager.cs.meta new file mode 100644 index 0000000..75e462a --- /dev/null +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/IPoolManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: de145ce4c4ec7204ebd525749f3d10cc \ No newline at end of file diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/PoolManager.cs b/Assets/Framework/Scripts/Utilities/ObjectPool/PoolManager.cs new file mode 100644 index 0000000..3b2f609 --- /dev/null +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/PoolManager.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using Framework.Core.Service; +using UnityEngine; + +namespace Framework.Utilities.ObjectPool +{ + [Service] + public class PoolManager : IPoolManager + { + private readonly Dictionary pools = new(); + + public IObjectPool CreatePool(string key, IObjectPool pool) + { + if (pools.ContainsKey(Hash(key))) + { + Debug.LogWarning($"Pool already exists for key:{key}"); + return pool; + } + + pools.Add(Hash(key), pool); + + return pool; + } + + public IObjectPool GetPool(string key = null) where T : class + { + if (pools.TryGetValue(Hash(key), out var p)) + return (IObjectPool)p; + return null; + } + + // 自动匹配类型, 尝试释放对象到对应池子 + public bool TryRelease(T item) where T : class + { + foreach (var p in pools.Values) + { + if (p is IObjectPool pool) + { + pool.Release(item); + return true; + } + } + return false; + } + + /// + /// 是否要做一层key的映射?使得出现不同类型的池子但是可以有相同名字 + /// + /// + /// + public string Hash(string key) + { + return key; + } + } +} \ No newline at end of file diff --git a/Assets/Framework/Scripts/Utilities/ObjectPool/PoolManager.cs.meta b/Assets/Framework/Scripts/Utilities/ObjectPool/PoolManager.cs.meta new file mode 100644 index 0000000..40aa2a7 --- /dev/null +++ b/Assets/Framework/Scripts/Utilities/ObjectPool/PoolManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7c3ccd0ef14ecac4598330b8539f3c8c \ No newline at end of file diff --git a/Assets/Framework/Tests/Utilities.meta b/Assets/Framework/Tests/Utilities.meta new file mode 100644 index 0000000..e8d3070 --- /dev/null +++ b/Assets/Framework/Tests/Utilities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10d7ff0ec3cd1f14ebc9ae5dc7a2612c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Framework/Tests/Utilities/PoolManagerTests.cs b/Assets/Framework/Tests/Utilities/PoolManagerTests.cs new file mode 100644 index 0000000..6490f52 --- /dev/null +++ b/Assets/Framework/Tests/Utilities/PoolManagerTests.cs @@ -0,0 +1,54 @@ +using UnityEngine; +using NUnit.Framework; +using Framework.Core.Service; +using Framework.Utilities.ObjectPool; + +namespace Tests +{ + public class PoolManagerTests + { + public GameObject prefab; + public GameObject parent; + public ServiceLocator serviceManager; + + [SetUp] + public void SetUp() + { + prefab = new GameObject("TestPrefab"); + serviceManager = new(); + parent = new GameObject("TestParent"); + serviceManager.RegisterSingleton(serviceManager); + } + + [Test] + public void CreateAndGetPool_Works() + { + var poolManager = serviceManager.Resolve(); + var pool = new GameobjectPool(parent.transform, prefab, 5, 20); + var returnedPool = poolManager.CreatePool("TestPool", pool); + Assert.AreEqual(pool, returnedPool); + var fetchPool = poolManager.GetPool("TestPool"); + Assert.AreEqual(pool, fetchPool); + } + + [Test] + public void PoolOperation_Works() + { + var poolManager = serviceManager.Resolve(); + var pool = new GameobjectPool(parent.transform, prefab, 5, 20); + poolManager.CreatePool("Op", pool); + var obj = pool.Get(); + Assert.IsNotNull(obj); + pool.Release(obj); + + var tryReleaseOut = poolManager.TryRelease(obj); + Assert.IsTrue(tryReleaseOut); + } + + [TearDown] + public void TearDown() + { + Object.DestroyImmediate(prefab); + } + } +} \ No newline at end of file diff --git a/Assets/Framework/Tests/Utilities/PoolManagerTests.cs.meta b/Assets/Framework/Tests/Utilities/PoolManagerTests.cs.meta new file mode 100644 index 0000000..b2bd801 --- /dev/null +++ b/Assets/Framework/Tests/Utilities/PoolManagerTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: bf1839294fb1397449539ada0d00e0d7 \ No newline at end of file