diff --git a/Assets/TEngine/EntryPrefab/TEngine.prefab b/Assets/TEngine/EntryPrefab/TEngine.prefab
index 1246a00d..32d417cc 100644
--- a/Assets/TEngine/EntryPrefab/TEngine.prefab
+++ b/Assets/TEngine/EntryPrefab/TEngine.prefab
@@ -1,5 +1,49 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
+--- !u!1 &1672025513
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 1672025514}
+ - component: {fileID: 1672025515}
+ m_Layer: 0
+ m_Name: ObjectPool
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &1672025514
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1672025513}
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: 0, y: 0, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_Children: []
+ m_Father: {fileID: 3463045026180535779}
+ m_RootOrder: 6
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &1672025515
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 1672025513}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: bef095b963a40b54fa82ba105bd1e98e, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ Limit: 100
--- !u!1 &3463045025307533287
GameObject:
m_ObjectHideFlags: 0
@@ -290,6 +334,7 @@ Transform:
- {fileID: 3463045025836799505}
- {fileID: 3463045026010536331}
- {fileID: 3463045025307533286}
+ - {fileID: 1672025514}
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
diff --git a/Assets/TEngine/Scripts/Editor/Inspector/ObjectPoolManagerInspector.cs b/Assets/TEngine/Scripts/Editor/Inspector/ObjectPoolManagerInspector.cs
new file mode 100644
index 00000000..d20f512b
--- /dev/null
+++ b/Assets/TEngine/Scripts/Editor/Inspector/ObjectPoolManagerInspector.cs
@@ -0,0 +1,41 @@
+using TEngine.Runtime;
+using UnityEditor;
+using UnityEngine;
+
+namespace TEngine.Editor
+{
+ [CustomEditor(typeof(ObjectPoolManager))]
+ internal sealed class ObjectPoolManagerInspector : TEngineInspector
+ {
+ public override void OnInspectorGUI()
+ {
+ if (!EditorApplication.isPlaying)
+ {
+ EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
+ return;
+ }
+
+ if (ObjectPoolManager.Instance.Helper.ObjectPools.Count == 0)
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.Label("No Runtime Data!");
+ GUILayout.EndHorizontal();
+ }
+
+ foreach (var pool in ObjectPoolManager.Instance.Helper.ObjectPools)
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.Space(20);
+ GUILayout.Label(pool.Key + ": " + pool.Value.Count);
+ GUILayout.FlexibleSpace();
+ GUI.enabled = pool.Value.Count > 0;
+ if (GUILayout.Button("Clear", EditorStyles.miniButton))
+ {
+ pool.Value.Clear();
+ }
+ GUI.enabled = true;
+ GUILayout.EndHorizontal();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Editor/Inspector/ObjectPoolManagerInspector.cs.meta b/Assets/TEngine/Scripts/Editor/Inspector/ObjectPoolManagerInspector.cs.meta
new file mode 100644
index 00000000..7488aa47
--- /dev/null
+++ b/Assets/TEngine/Scripts/Editor/Inspector/ObjectPoolManagerInspector.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a49fa7335fa305d4bbef4478b39ed39a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/Core/Utility/Utility.GameObjectUtils.cs b/Assets/TEngine/Scripts/Runtime/Core/Utility/Utility.GameObjectUtils.cs
new file mode 100644
index 00000000..2d21de83
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/Core/Utility/Utility.GameObjectUtils.cs
@@ -0,0 +1,180 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace TEngine.Runtime
+{
+ public static partial class Utility
+ {
+ ///
+ /// GameObject相关的实用函数。
+ ///
+ public static class GameObjectUtils
+ {
+ #region Static Method
+
+ ///
+ /// 克隆实例
+ ///
+ /// 实例类型
+ /// 初始对象
+ /// 克隆的新对象
+ public static T Clone(T original) where T : Object
+ {
+ return Object.Instantiate(original);
+ }
+
+ ///
+ /// 克隆实例
+ ///
+ /// 实例类型
+ /// 初始对象
+ /// 新对象的位置
+ /// 新对象的旋转
+ /// 克隆的新对象
+ public static T Clone(T original, Vector3 position, Quaternion rotation) where T : Object
+ {
+ return Object.Instantiate(original, position, rotation);
+ }
+
+ ///
+ /// 克隆实例
+ ///
+ /// 实例类型
+ /// 初始对象
+ /// 新对象的位置
+ /// 新对象的旋转
+ /// 新对象的父物体
+ /// 克隆的新对象
+ public static T Clone(T original, Vector3 position, Quaternion rotation, Transform parent)
+ where T : Object
+ {
+ return Object.Instantiate(original, position, rotation, parent);
+ }
+
+ ///
+ /// 克隆实例
+ ///
+ /// 实例类型
+ /// 初始对象
+ /// 新对象的父物体
+ /// 克隆的新对象
+ public static T Clone(T original, Transform parent) where T : Object
+ {
+ return Object.Instantiate(original, parent);
+ }
+
+ ///
+ /// 克隆实例
+ ///
+ /// 实例类型
+ /// 初始对象
+ /// 新对象的父物体
+ /// 是否保持世界位置不变
+ /// 克隆的新对象
+ public static T Clone(T original, Transform parent, bool worldPositionStays) where T : Object
+ {
+ return Object.Instantiate(original, parent, worldPositionStays);
+ }
+
+ ///
+ /// 克隆 GameObject 实例
+ ///
+ /// 初始对象
+ /// 是否是UI对象
+ /// 克隆的新对象
+ public static GameObject CloneGameObject(GameObject original, bool isUI = false)
+ {
+ GameObject obj = Object.Instantiate(original);
+ obj.transform.SetParent(original.transform.parent);
+ if (isUI)
+ {
+ RectTransform rect = obj.rectTransform();
+ RectTransform originalRect = original.rectTransform();
+ rect.anchoredPosition3D = originalRect.anchoredPosition3D;
+ rect.sizeDelta = originalRect.sizeDelta;
+ rect.offsetMin = originalRect.offsetMin;
+ rect.offsetMax = originalRect.offsetMax;
+ rect.anchorMin = originalRect.anchorMin;
+ rect.anchorMax = originalRect.anchorMax;
+ rect.pivot = originalRect.pivot;
+ }
+ else
+ {
+ obj.transform.localPosition = original.transform.localPosition;
+ }
+
+ obj.transform.localRotation = original.transform.localRotation;
+ obj.transform.localScale = original.transform.localScale;
+ obj.SetActive(true);
+ return obj;
+ }
+
+ ///
+ /// 杀死实例
+ ///
+ /// 实例对象
+ public static void Kill(Object obj)
+ {
+ Object.Destroy(obj);
+ }
+
+ ///
+ /// 立即杀死实例
+ ///
+ /// 实例对象
+ public static void KillImmediate(Object obj)
+ {
+ Object.DestroyImmediate(obj);
+ }
+
+ ///
+ /// 杀死一群实例
+ ///
+ /// 实例类型
+ /// 实例集合
+ public static void Kills(List objs) where T : Object
+ {
+ for (int i = 0; i < objs.Count; i++)
+ {
+ Object.Destroy(objs[i]);
+ }
+
+ objs.Clear();
+ }
+
+ ///
+ /// 杀死一群实例
+ ///
+ /// 实例类型
+ /// 实例数组
+ public static void Kills(T[] objs) where T : Object
+ {
+ for (int i = 0; i < objs.Length; i++)
+ {
+ Object.Destroy(objs[i]);
+ }
+ }
+
+ #endregion
+ }
+ }
+
+ public static class GameObjectExt
+ {
+ ///
+ /// 获取RectTransform组件
+ ///
+ public static RectTransform rectTransform(this GameObject obj)
+ {
+ return obj.GetComponent();
+ }
+
+ ///
+ /// 获取RectTransform组件
+ ///
+ public static RectTransform rectTransform(this MonoBehaviour mono)
+ {
+ return mono.GetComponent();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/Core/Utility/Utility.GameObjectUtils.cs.meta b/Assets/TEngine/Scripts/Runtime/Core/Utility/Utility.GameObjectUtils.cs.meta
new file mode 100644
index 00000000..b896f02d
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/Core/Utility/Utility.GameObjectUtils.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 8a631f70e55a4d419de768a51347edab
+timeCreated: 1662280007
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool.meta b/Assets/TEngine/Scripts/Runtime/ObjectPool.meta
new file mode 100644
index 00000000..1ad3cbea
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 18905312db3bc3d448630110b4a9bcd3
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper.meta b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper.meta
new file mode 100644
index 00000000..cc235d82
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: eaa7867dbaa447e42b63eb98f3dd8687
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/DefaultObjectPoolHelper.cs b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/DefaultObjectPoolHelper.cs
new file mode 100644
index 00000000..956da101
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/DefaultObjectPoolHelper.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace TEngine.Runtime
+{
+ ///
+ /// 默认的对象池管理器助手
+ ///
+ public sealed class DefaultObjectPoolHelper : IObjectPoolHelper
+ {
+ ///
+ /// 对象池默认上限
+ ///
+ private int _limit;
+
+ ///
+ /// 所有对象池
+ ///
+ public Dictionary ObjectPools { get; private set; } =
+ new Dictionary();
+
+ ///
+ /// 初始化助手
+ ///
+ public DefaultObjectPoolHelper()
+ {
+ _limit = ObjectPoolManager.Instance.Limit;
+ }
+
+ ///
+ /// ShutDown
+ ///
+ public void ShutDown()
+ {
+ ClearAll();
+ }
+
+ ///
+ /// 注册对象池
+ ///
+ /// 对象池名称
+ /// 对象模板
+ /// 对象生成时初始化委托
+ /// 对象回收时处理委托
+ /// 对象池上限,等于0时,表示使用默认值
+ public void RegisterPool(string name, GameObject allocItem, Action onAlloc,
+ Action onRelease, int limit)
+ {
+ if (allocItem == null)
+ return;
+
+ if (!ObjectPools.ContainsKey(name))
+ {
+ ObjectPools.Add(name, new ObjectPool(allocItem, limit <= 0 ? _limit : limit, onAlloc, onRelease));
+ }
+ else
+ {
+ Log.Error("注册对象池失败:已存在对象池 " + name + " !");
+ }
+ }
+
+ ///
+ /// 是否存在指定名称的对象池
+ ///
+ /// 对象池名称
+ /// 是否存在
+ public bool IsExistPool(string name)
+ {
+ return ObjectPools.ContainsKey(name);
+ }
+
+ ///
+ /// 移除已注册的对象池
+ ///
+ /// 对象池名称
+ public void UnRegisterPool(string name)
+ {
+ if (ObjectPools.ContainsKey(name))
+ {
+ ObjectPools[name].Clear();
+ ObjectPools.Remove(name);
+ }
+ else
+ {
+ Log.Error("移除对象池失败:不存在对象池 " + name + " !");
+ }
+ }
+
+ ///
+ /// 获取对象池中对象数量
+ ///
+ /// 对象池名称
+ /// 对象数量
+ public int GetPoolCount(string name)
+ {
+ if (ObjectPools.ContainsKey(name))
+ {
+ return ObjectPools[name].Count;
+ }
+ else
+ {
+ Log.Warning("获取对象数量失败:不存在对象池 " + name + " !");
+ return 0;
+ }
+ }
+
+ ///
+ /// 生成对象
+ ///
+ /// 对象池名称
+ /// 对象
+ public GameObject Alloc(string name)
+ {
+ if (ObjectPools.ContainsKey(name))
+ {
+ return ObjectPools[name].Alloc();
+ }
+ else
+ {
+ Log.Error("生成对象失败:不存在对象池 " + name + " !");
+ return null;
+ }
+ }
+
+ ///
+ /// 回收对象
+ ///
+ /// 对象池名称
+ /// 对象
+ public void Release(string name, GameObject target)
+ {
+ if (target == null)
+ return;
+
+ if (ObjectPools.ContainsKey(name))
+ {
+ ObjectPools[name].Release(target);
+ }
+ else
+ {
+ Log.Error("回收对象失败:不存在对象池 " + name + " !");
+ }
+ }
+
+ ///
+ /// 批量回收对象
+ ///
+ /// 对象池名称
+ /// 对象数组
+ public void Releases(string name, GameObject[] targets)
+ {
+ if (targets == null)
+ return;
+
+ if (ObjectPools.ContainsKey(name))
+ {
+ for (int i = 0; i < targets.Length; i++)
+ {
+ ObjectPools[name].Release(targets[i]);
+ }
+ }
+ else
+ {
+ Log.Error("回收对象失败:不存在对象池 " + name + " !");
+ }
+ }
+
+ ///
+ /// 批量回收对象
+ ///
+ /// 对象池名称
+ /// 对象集合
+ public void Releases(string name, List targets)
+ {
+ if (targets == null)
+ return;
+
+ if (ObjectPools.ContainsKey(name))
+ {
+ for (int i = 0; i < targets.Count; i++)
+ {
+ ObjectPools[name].Release(targets[i]);
+ }
+
+ targets.Clear();
+ }
+ else
+ {
+ Log.Error("回收对象失败:不存在对象池 " + name + " !");
+ }
+ }
+
+ ///
+ /// 清空指定的对象池
+ ///
+ /// 对象池名称
+ public void Clear(string name)
+ {
+ if (ObjectPools.ContainsKey(name))
+ {
+ ObjectPools[name].Clear();
+ }
+ else
+ {
+ Log.Error("清空对象池失败:不存在对象池 " + name + " !");
+ }
+ }
+
+ ///
+ /// 清空所有对象池
+ ///
+ public void ClearAll()
+ {
+ foreach (var pool in ObjectPools)
+ {
+ pool.Value.Clear();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/DefaultObjectPoolHelper.cs.meta b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/DefaultObjectPoolHelper.cs.meta
new file mode 100644
index 00000000..646e2226
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/DefaultObjectPoolHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7f19a0d9040fd24439a22aa1b33b1752
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 701b9bfeb6deef341a599f8d0f1ec080, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/IObjectPoolHelper.cs b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/IObjectPoolHelper.cs
new file mode 100644
index 00000000..84d3abd3
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/IObjectPoolHelper.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace TEngine.Runtime
+{
+ ///
+ /// 对象池管理器的助手接口
+ ///
+ public interface IObjectPoolHelper
+ {
+ ///
+ /// 所有对象池
+ ///
+ Dictionary ObjectPools { get; }
+
+ ///
+ /// 注册对象池
+ ///
+ /// 对象池名称
+ /// 对象模板
+ /// 对象生成时初始化委托
+ /// 对象回收时处理委托
+ /// 对象池上限,等于0时,表示使用默认值
+ void RegisterPool(string name, GameObject allocItem, Action onAlloc,
+ Action onRelease, int limit);
+
+ ///
+ /// 是否存在指定名称的对象池
+ ///
+ /// 对象池名称
+ /// 是否存在
+ bool IsExistPool(string name);
+
+ ///
+ /// 移除已注册的对象池
+ ///
+ /// 对象池名称
+ void UnRegisterPool(string name);
+
+ ///
+ /// 获取对象池中对象数量
+ ///
+ /// 对象池名称
+ /// 对象数量
+ int GetPoolCount(string name);
+
+ ///
+ /// 生成对象
+ ///
+ /// 对象池名称
+ /// 对象
+ GameObject Alloc(string name);
+
+ ///
+ /// 回收对象
+ ///
+ /// 对象池名称
+ /// 对象
+ void Release(string name, GameObject target);
+
+ ///
+ /// 批量回收对象
+ ///
+ /// 对象池名称
+ /// 对象数组
+ void Releases(string name, GameObject[] targets);
+
+ ///
+ /// 批量回收对象
+ ///
+ /// 对象池名称
+ /// 对象集合
+ void Releases(string name, List targets);
+
+ ///
+ /// 清空指定的对象池
+ ///
+ /// 对象池名称
+ void Clear(string name);
+
+ ///
+ /// 清空所有对象池
+ ///
+ void ClearAll();
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/IObjectPoolHelper.cs.meta b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/IObjectPoolHelper.cs.meta
new file mode 100644
index 00000000..5c62b232
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/IObjectPoolHelper.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9f0af4beea5247d40a447b27c807de3a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 701b9bfeb6deef341a599f8d0f1ec080, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/ObjectPool.cs b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/ObjectPool.cs
new file mode 100644
index 00000000..3a9a41f1
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/ObjectPool.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace TEngine.Runtime
+{
+ ///
+ /// 对象池
+ ///
+ public sealed class ObjectPool
+ {
+ private readonly GameObject _allocItem;
+ private readonly int _limit = 100;
+ private readonly Queue _objectQueue = new Queue();
+ private readonly Action _onAlloc;
+ private readonly Action _onRelease;
+
+ ///
+ /// 对象数量
+ ///
+ public int Count
+ {
+ get { return _objectQueue.Count; }
+ }
+
+ ///
+ /// 构造函数对象池
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ObjectPool(GameObject allocItem, int limit, Action onAlloc,
+ Action onRelease)
+ {
+ _allocItem = allocItem;
+ _limit = limit;
+ _onAlloc = onAlloc;
+ _onRelease = onRelease;
+ }
+
+ ///
+ /// 生成对象
+ ///
+ /// 对象
+ public GameObject Alloc()
+ {
+ GameObject obj;
+ if (_objectQueue.Count > 0)
+ {
+ obj = _objectQueue.Dequeue();
+ }
+ else
+ {
+ obj = Utility.GameObjectUtils.CloneGameObject(_allocItem);
+ }
+
+ obj.SetActive(true);
+
+ obj.transform.SetParent(null);
+
+ _onAlloc?.Invoke(obj);
+
+ return obj;
+ }
+
+ ///
+ /// 回收对象
+ ///
+ /// 对象
+ public void Release(GameObject obj)
+ {
+ if (_objectQueue.Count >= _limit)
+ {
+ _onRelease?.Invoke(obj);
+
+ Utility.GameObjectUtils.Kill(obj);
+ }
+ else
+ {
+ obj.SetActive(false);
+
+ _onRelease?.Invoke(obj);
+
+ _objectQueue.Enqueue(obj);
+
+ obj.transform.SetParent(ObjectPoolManager.Instance.gameObject.transform);
+ }
+ }
+
+ ///
+ /// 清空所有对象
+ ///
+ public void Clear()
+ {
+ while (_objectQueue.Count > 0)
+ {
+ GameObject obj = _objectQueue.Dequeue();
+ if (obj)
+ {
+ Utility.GameObjectUtils.Kill(obj);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/ObjectPool.cs.meta b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/ObjectPool.cs.meta
new file mode 100644
index 00000000..d1d11628
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/Helper/ObjectPool.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 27382aff833de094e97dd246ad567aad
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {fileID: 2800000, guid: 701b9bfeb6deef341a599f8d0f1ec080, type: 3}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/ObjectPoolManager.cs b/Assets/TEngine/Scripts/Runtime/ObjectPool/ObjectPoolManager.cs
new file mode 100644
index 00000000..e2843c3f
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/ObjectPoolManager.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace TEngine.Runtime
+{
+ ///
+ /// 对象池管理器
+ ///
+ public sealed class ObjectPoolManager : UnitySingleton
+ {
+ private IObjectPoolHelper _helper;
+
+ public IObjectPoolHelper Helper => _helper;
+
+ public override int Priority => -1;
+
+ public override void Awake()
+ {
+ base.Awake();
+ _helper = new DefaultObjectPoolHelper();
+ }
+
+ ///
+ /// 单个对象池上限
+ ///
+ [SerializeField] internal int Limit = 100;
+
+ ///
+ /// 注册对象池
+ ///
+ /// 对象池名称
+ /// 对象模板
+ /// 对象生成时初始化委托
+ /// 对象回收时处理委托
+ /// 对象池上限,等于0时,表示使用默认值
+ public void RegisterPool(string name, GameObject allocItem, Action onAlloc = null,
+ Action onRelease = null, int limit = 0)
+ {
+ _helper.RegisterPool(name, allocItem, onAlloc, onRelease, limit);
+ }
+
+ ///
+ /// 是否存在指定名称的对象池
+ ///
+ /// 对象池名称
+ /// 是否存在
+ public bool IsExistPool(string name)
+ {
+ return _helper.IsExistPool(name);
+ }
+
+ ///
+ /// 移除已注册的对象池
+ ///
+ /// 对象池名称
+ public void UnRegisterPool(string name)
+ {
+ _helper.UnRegisterPool(name);
+ }
+
+ ///
+ /// 获取对象池中对象数量
+ ///
+ /// 对象池名称
+ /// 对象数量
+ public int GetPoolCount(string name)
+ {
+ return _helper.GetPoolCount(name);
+ }
+
+ ///
+ /// 生成对象
+ ///
+ /// 对象池名称
+ /// 对象
+ public GameObject Alloc(string name)
+ {
+ return _helper.Alloc(name);
+ }
+
+ ///
+ /// 回收对象
+ ///
+ /// 对象池名称
+ /// 对象
+ public void Release(string name, GameObject target)
+ {
+ _helper.Release(name, target);
+ }
+
+ ///
+ /// 批量回收对象
+ ///
+ /// 对象池名称
+ /// 对象数组
+ public void Releases(string name, GameObject[] targets)
+ {
+ _helper.Releases(name, targets);
+ }
+
+ ///
+ /// 批量回收对象
+ ///
+ /// 对象池名称
+ /// 对象集合
+ public void Releases(string name, List targets)
+ {
+ _helper.Releases(name, targets);
+ }
+
+ ///
+ /// 清空指定的对象池
+ ///
+ /// 对象池名称
+ public void Clear(string name)
+ {
+ _helper.Clear(name);
+ }
+
+ ///
+ /// 清空所有对象池
+ ///
+ public void ClearAll()
+ {
+ _helper.ClearAll();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TEngine/Scripts/Runtime/ObjectPool/ObjectPoolManager.cs.meta b/Assets/TEngine/Scripts/Runtime/ObjectPool/ObjectPoolManager.cs.meta
new file mode 100644
index 00000000..fccde163
--- /dev/null
+++ b/Assets/TEngine/Scripts/Runtime/ObjectPool/ObjectPoolManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: bef095b963a40b54fa82ba105bd1e98e
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: