26 changed files with 2471 additions and 75 deletions
@ -0,0 +1,106 @@
|
||||
using System.Collections.Generic; |
||||
using UnityEditor; |
||||
using UnityEngine; |
||||
|
||||
namespace Tools.EasyPoolKit.Editor |
||||
{ |
||||
[CustomEditor(typeof(RecyclableGOPoolKit))] |
||||
public class RecyclableGOPoolKitInspector : UnityEditor.Editor |
||||
{ |
||||
private readonly HashSet<string> _poolIdsSet = new HashSet<string>(); |
||||
|
||||
public override void OnInspectorGUI() |
||||
{ |
||||
if (!EditorApplication.isPlaying) |
||||
{ |
||||
EditorGUILayout.HelpBox("Available only on runtime.", MessageType.Info); |
||||
return; |
||||
} |
||||
|
||||
var poolMgr = target as RecyclableGOPoolKit; |
||||
|
||||
if (poolMgr) |
||||
{ |
||||
EditorGUILayout.LabelField("RecyclableGOPoolManager"); |
||||
|
||||
var poolsInfo = poolMgr.GetPoolsInfo(); |
||||
|
||||
EditorGUILayout.LabelField("GameObject Pool Count", poolsInfo.Count.ToString()); |
||||
|
||||
for (int i = 0; i < poolsInfo.Count; i++) |
||||
{ |
||||
var poolInfo = poolsInfo[i]; |
||||
DrawGameObjectPool(poolInfo); |
||||
} |
||||
} |
||||
|
||||
Repaint(); |
||||
} |
||||
|
||||
private void DrawGameObjectPool(RecyclablePoolInfo poolInfo) |
||||
{ |
||||
var ifLastOpened = _poolIdsSet.Contains(poolInfo.PoolId); |
||||
var ifCurOpened = EditorGUILayout.Foldout(ifLastOpened, poolInfo.PoolId); |
||||
|
||||
if (ifCurOpened != ifLastOpened) |
||||
{ |
||||
if (ifCurOpened) |
||||
{ |
||||
_poolIdsSet.Add(poolInfo.PoolId); |
||||
} |
||||
else |
||||
{ |
||||
_poolIdsSet.Remove(poolInfo.PoolId); |
||||
} |
||||
} |
||||
|
||||
if (ifCurOpened) |
||||
{ |
||||
EditorGUILayout.BeginVertical("box"); |
||||
{ |
||||
EditorGUILayout.LabelField("PoolId", poolInfo.PoolId); |
||||
EditorGUILayout.LabelField("ReferenceType", poolInfo.ReferenceType.ToString()); |
||||
EditorGUILayout.LabelField("InitCreateCount", poolInfo.InitCreateCount.HasValue ? poolInfo.InitCreateCount.Value.ToString() : "-"); |
||||
EditorGUILayout.LabelField("ReachMaxLimitType", poolInfo.ReachMaxLimitType.ToString()); |
||||
if (poolInfo.ReachMaxLimitType != PoolReachMaxLimitType.Default) |
||||
{ |
||||
EditorGUILayout.LabelField("MaxSpawnCount", poolInfo.MaxSpawnCount.HasValue ? poolInfo.MaxSpawnCount.Value.ToString() : "-"); |
||||
} |
||||
EditorGUILayout.LabelField("DespawnDestroyType", poolInfo.DespawnDestroyType.ToString()); |
||||
if (poolInfo.DespawnDestroyType == PoolDespawnDestroyType.DestroyToLimit) |
||||
{ |
||||
EditorGUILayout.LabelField("MaxDespawnCount", poolInfo.MaxDespawnCount.HasValue ? poolInfo.MaxDespawnCount.Value.ToString() : "-"); |
||||
} |
||||
|
||||
EditorGUILayout.LabelField("ClearType", poolInfo.ClearType.ToString()); |
||||
EditorGUILayout.LabelField("AutoClearTime", poolInfo.AutoClearTime.ToString()); |
||||
EditorGUILayout.LabelField("IfIgnoreTimeScale", poolInfo.IsIgnoreTimeScale.ToString()); |
||||
EditorGUILayout.LabelField("CachedObjectCount", poolInfo.CachedObjectCount.ToString()); |
||||
EditorGUILayout.LabelField("UsedObjectCount", poolInfo.UsedObjectCount.ToString()); |
||||
EditorGUILayout.LabelField("TotalObjectCount", poolInfo.TotalObjectCount.ToString()); |
||||
|
||||
if (GUILayout.Button("ClearUnusedObjects(Safe)")) |
||||
{ |
||||
if (poolInfo.ExtraInfo is RecyclableGameObjectPool pool) |
||||
{ |
||||
pool.ClearUnusedObjects(); |
||||
} |
||||
} |
||||
|
||||
if (GUILayout.Button("ClearPool(Unsafe)")) |
||||
{ |
||||
if (poolInfo.ExtraInfo is RecyclableGameObjectPool pool) |
||||
{ |
||||
pool.ClearAll(); |
||||
} |
||||
} |
||||
|
||||
//TODO Draw all Objects |
||||
} |
||||
EditorGUILayout.EndVertical(); |
||||
|
||||
EditorGUILayout.Separator(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 4f91df83af2a4b1783596dc115062a57 |
||||
timeCreated: 1735968672 |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 1b4c6592766748e9850e7f96f3242d3b |
||||
timeCreated: 1735963479 |
@ -0,0 +1,51 @@
|
||||
using System; |
||||
using NUnit.Framework; |
||||
using UnityEngine; |
||||
|
||||
namespace Tools.EasyPoolKit |
||||
{ |
||||
public class RecyclableGOPoolKit : RecyclableGOPoolManagerBase |
||||
{ |
||||
public static RecyclableGOPoolKit Instance |
||||
{ |
||||
get |
||||
{ |
||||
if (_instance == null) |
||||
{ |
||||
var poolRoot = new GameObject("RecyclableGOPoolKit"); |
||||
var cachedRoot = new GameObject("CachedRoot"); |
||||
cachedRoot.transform.SetParent(poolRoot.transform, false); |
||||
cachedRoot.gameObject.SetActive(false); |
||||
_instance = poolRoot.AddComponent<RecyclableGOPoolKit>(); |
||||
_instance.CachedRoot = cachedRoot.transform; |
||||
DontDestroyOnLoad(_instance.gameObject); |
||||
} |
||||
return _instance; |
||||
} |
||||
} |
||||
private static RecyclableGOPoolKit _instance; |
||||
|
||||
private void Awake() |
||||
{ |
||||
if (_instance != null) |
||||
{ |
||||
Debug.LogError("EasyPoolKit == Don't attach RecyclableGOPoolManager on any object, use SimpleGOPoolManager.Instance instead!"); |
||||
Destroy(gameObject); |
||||
} |
||||
} |
||||
|
||||
public override RecyclablePoolConfig GetDefaultPrefabPoolConfig(string poolPrefix, GameObject prefabAsset, Func<RecyclableMonoBehaviour> spawnFunc) |
||||
{ |
||||
Assert.IsNotNull(prefabAsset); |
||||
var poolConfig = new RecyclablePoolConfig() |
||||
{ |
||||
ObjectType = RecycleObjectType.RecyclableGameObject, |
||||
ReferenceType = typeof(GameObject), |
||||
PoolId = $"RecyclableGOPool_{poolPrefix ?? string.Empty}_{prefabAsset.GetInstanceID()}", |
||||
SpawnFunc = spawnFunc, |
||||
}; |
||||
|
||||
return poolConfig; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 8cff55e0843e4bd0875e328d0b7216d5 |
||||
timeCreated: 1735965986 |
@ -0,0 +1,230 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using UnityEngine; |
||||
using UnityEngine.Assertions; |
||||
|
||||
namespace Tools.EasyPoolKit |
||||
{ |
||||
public abstract class RecyclableGOPoolManagerBase : MonoBehaviour |
||||
{ |
||||
public string PoolPrefix = string.Empty; |
||||
|
||||
/// 缓存根节点 |
||||
protected Transform CachedRoot; |
||||
|
||||
/// key: 预制体的HashID, value: 对应的预制体 |
||||
private Dictionary<int, GameObject> _prefabTemplates = new Dictionary<int, GameObject>(); |
||||
|
||||
/// key: 预制体的HashID, value: 对应的对象池 |
||||
private Dictionary<int, RecyclableGameObjectPool> _gameObjPools = new Dictionary<int, RecyclableGameObjectPool>(); |
||||
|
||||
/// key: 激活的物体实例的HashID, value: 对应的预制体的HashID |
||||
private List<RecyclablePoolInfo> _poolInfoList = new List<RecyclablePoolInfo>(); |
||||
public List<RecyclablePoolInfo> GetPoolsInfo() => _poolInfoList; |
||||
|
||||
private bool _ifAppQuit = false; |
||||
|
||||
/// 检测是否已有对应的对象池 |
||||
public bool IfPoolValid(int prefabHash) => _prefabTemplates.ContainsKey(prefabHash) && _gameObjPools.ContainsKey(prefabHash); |
||||
|
||||
private void Update() |
||||
{ |
||||
foreach (var poolPair in _gameObjPools) |
||||
{ |
||||
var pool = poolPair.Value; |
||||
var deltaTime = pool.IsIgnoreTimeScale ? Time.unscaledDeltaTime : Time.deltaTime; |
||||
pool.OnPoolUpdate(deltaTime); |
||||
} |
||||
} |
||||
|
||||
private void OnApplicationQuit() |
||||
{ |
||||
_ifAppQuit = true; |
||||
} |
||||
|
||||
private void OnDestroy() |
||||
{ |
||||
if (!_ifAppQuit) |
||||
{ |
||||
ClearAllPools(true); |
||||
} |
||||
} |
||||
|
||||
|
||||
public RecyclableGameObjectPool RegisterPrefab(GameObject prefabAsset, RecyclablePoolConfig config = null) |
||||
{ |
||||
Assert.IsNotNull(prefabAsset); |
||||
|
||||
var prefabHash = prefabAsset.GetInstanceID(); |
||||
|
||||
#if EASY_POOL_DEBUG |
||||
if (_gameObjPools.ContainsKey(prefabHash) || _prefabTemplates.ContainsKey(prefabHash)) |
||||
{ |
||||
Debug.LogError($"EasyPoolKit == RegisterPrefab {prefabAsset.name} but already registered"); |
||||
return null; |
||||
} |
||||
#endif |
||||
|
||||
if (config == null) |
||||
{ |
||||
config = GetDefaultPrefabPoolConfig(PoolPrefix, prefabAsset, null); |
||||
} |
||||
|
||||
if (config.SpawnFunc == null) |
||||
{ |
||||
config.SpawnFunc = () => DefaultCreateObjectFunc(prefabHash); |
||||
} |
||||
|
||||
if (config.ExtraArgs == null || config.ExtraArgs.Length == 0) |
||||
{ |
||||
config.ExtraArgs = new object[] { CachedRoot }; |
||||
} |
||||
|
||||
_prefabTemplates[prefabHash] = prefabAsset; |
||||
var newPool = new RecyclableGameObjectPool(config); |
||||
_gameObjPools[prefabHash] = newPool; |
||||
_poolInfoList.Add(newPool.GetPoolInfoReadOnly()); |
||||
|
||||
return newPool; |
||||
} |
||||
|
||||
public bool UnRegisterPrefab(int prefabHash) |
||||
{ |
||||
_prefabTemplates.Remove(prefabHash); |
||||
|
||||
if (_gameObjPools.TryGetValue(prefabHash, out var pool)) |
||||
{ |
||||
pool.ClearAll(); |
||||
_poolInfoList.Remove(pool.GetPoolInfoReadOnly()); |
||||
_gameObjPools.Remove(prefabHash); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
|
||||
public RecyclableMonoBehaviour SimpleSpawn(GameObject prefabTemplate) |
||||
{ |
||||
if (prefabTemplate == null) |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
var prefabHash = prefabTemplate.GetInstanceID(); |
||||
|
||||
if (!_gameObjPools.TryGetValue(prefabHash, out var pool)) |
||||
{ |
||||
pool = RegisterPrefab(prefabTemplate); |
||||
} |
||||
|
||||
return pool.SpawnObject(); |
||||
} |
||||
|
||||
public T SimpleSpawn<T>(GameObject prefabTemplate) where T :RecyclableMonoBehaviour |
||||
{ |
||||
return SimpleSpawn(prefabTemplate) as T; |
||||
} |
||||
|
||||
public bool TrySpawn(int prefabHash, out RecyclableMonoBehaviour recyclableObj) |
||||
{ |
||||
recyclableObj = null; |
||||
if (_gameObjPools.TryGetValue(prefabHash, out var pool)) |
||||
{ |
||||
recyclableObj = pool.SpawnObject(); |
||||
} |
||||
|
||||
return recyclableObj != null; |
||||
} |
||||
|
||||
public bool TrySpawn<T>(int prefabHash, out T recyclableObj) where T :RecyclableMonoBehaviour |
||||
{ |
||||
recyclableObj = null; |
||||
if (TrySpawn(prefabHash, out var newObj)) |
||||
{ |
||||
recyclableObj = newObj as T; |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public bool Despawn(RecyclableMonoBehaviour recyclableObj) |
||||
{ |
||||
Assert.IsNotNull(recyclableObj); |
||||
return recyclableObj.DespawnSelf(); |
||||
} |
||||
|
||||
public bool ClearPoolByAssetHash(int prefabHash, bool onlyClearUnused = false) |
||||
{ |
||||
if (_gameObjPools.TryGetValue(prefabHash, out var pool)) |
||||
{ |
||||
if (onlyClearUnused) |
||||
{ |
||||
pool.ClearUnusedObjects(); |
||||
return true; |
||||
} |
||||
else |
||||
{ |
||||
pool.ClearAll(); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public void ClearAllUnusedObjects() |
||||
{ |
||||
foreach (var poolPair in _gameObjPools) |
||||
{ |
||||
poolPair.Value.ClearUnusedObjects(); |
||||
} |
||||
} |
||||
|
||||
public void ClearAllPools(bool ifDestroy) |
||||
{ |
||||
foreach (var pool in _gameObjPools) |
||||
{ |
||||
pool.Value.ClearAll(); |
||||
} |
||||
|
||||
if (ifDestroy) |
||||
{ |
||||
if (CachedRoot) |
||||
{ |
||||
for (int i = CachedRoot.childCount - 1; i >= 0; i--) |
||||
{ |
||||
var child = CachedRoot.GetChild(i).gameObject; |
||||
Destroy(child); |
||||
} |
||||
} |
||||
|
||||
_prefabTemplates.Clear(); |
||||
_poolInfoList.Clear(); |
||||
_gameObjPools.Clear(); |
||||
} |
||||
} |
||||
|
||||
private RecyclableMonoBehaviour DefaultCreateObjectFunc(int prefabHash) |
||||
{ |
||||
if (_prefabTemplates.TryGetValue(prefabHash, out var prefabAsset)) |
||||
{ |
||||
if (prefabAsset != null) |
||||
{ |
||||
var gameObj = Instantiate(prefabAsset); |
||||
var recyclableObj = gameObj.GetOrCreateRecyclableMono(); |
||||
recyclableObj.PrefabHash = prefabHash; |
||||
return recyclableObj; |
||||
} |
||||
} |
||||
|
||||
Debug.LogError($"EasyPoolKit == Cannot create object: {prefabHash}"); |
||||
return null; |
||||
} |
||||
|
||||
public abstract RecyclablePoolConfig GetDefaultPrefabPoolConfig(string poolPrefix, GameObject prefabAsset, |
||||
Func<RecyclableMonoBehaviour> spawnFunc); |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 8cde1003a7854925ac58c691ed66bdf9 |
||||
timeCreated: 1735966230 |
@ -0,0 +1,49 @@
|
||||
using UnityEngine; |
||||
|
||||
namespace Tools.EasyPoolKit |
||||
{ |
||||
public class RecyclableGameObjectPool : RecyclablePoolBase<RecyclableMonoBehaviour> |
||||
{ |
||||
private Transform _cachedRoot; |
||||
|
||||
public RecyclableGameObjectPool(RecyclablePoolConfig config) : base(config) { } |
||||
|
||||
protected override void OnInitByParams(object[] args) |
||||
{ |
||||
var extraArgs = args; |
||||
|
||||
if (extraArgs != null && extraArgs.Length > 0 && extraArgs[0] is Transform root) |
||||
{ |
||||
_cachedRoot = root; |
||||
} |
||||
else |
||||
{ |
||||
Debug.LogError("EasyPoolKit == Create RecyclableMonoPool should input the root Transform in extraArgs[0]"); |
||||
} |
||||
} |
||||
|
||||
protected override void OnObjectInit(RecyclableMonoBehaviour usedObj) |
||||
{ |
||||
usedObj.Pool = this; |
||||
usedObj.PoolId = PoolId; |
||||
} |
||||
|
||||
protected override void OnObjectEnqueue(RecyclableMonoBehaviour usedObj) |
||||
{ |
||||
usedObj.transform.SetParent(_cachedRoot, true); |
||||
} |
||||
|
||||
protected override void OnObjectDequeue(RecyclableMonoBehaviour usedObj) |
||||
{ |
||||
usedObj.transform.SetParent(null, true); |
||||
} |
||||
|
||||
protected override void OnObjectDestoryInit(RecyclableMonoBehaviour usedObj) |
||||
{ |
||||
if (usedObj) |
||||
{ |
||||
Object.Destroy(usedObj.gameObject); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 6ab2cfde92374470825bf4ff3b0ac5a3 |
||||
timeCreated: 1735964092 |
@ -0,0 +1,88 @@
|
||||
using UnityEngine; |
||||
using UnityEngine.Assertions; |
||||
|
||||
namespace Tools.EasyPoolKit |
||||
{ |
||||
public class RecyclableMonoBehaviour : MonoBehaviour, IRecyclable |
||||
{ |
||||
public bool EnableMessage = false; |
||||
|
||||
public RecyclableGameObjectPool Pool { get; set; } |
||||
|
||||
public static readonly string MessageOnInit = "OnObjectInit"; |
||||
public static readonly string MessageOnDeInit = "OnObjectDeInit"; |
||||
public static readonly string MessageOnSpawn = "OnObjectSpawn"; |
||||
public static readonly string MessageOnDespawn = "OnObjectDespawn"; |
||||
|
||||
public RecycleObjectType ObjectType => RecycleObjectType.RecyclableGameObject; |
||||
public string PoolId { get; set; } |
||||
public int ObjectId { get; set; } |
||||
public string Name { get => gameObject.name; set => gameObject.name = value; } |
||||
public float UsedTime { get; set; } |
||||
|
||||
public int PrefabHash { get; set; } |
||||
|
||||
public virtual void OnObjectInit() |
||||
{ |
||||
if (EnableMessage) |
||||
{ |
||||
SendMessage(MessageOnInit, SendMessageOptions.DontRequireReceiver); |
||||
} |
||||
} |
||||
|
||||
public virtual void OnObjectDestroyInit() |
||||
{ |
||||
if (EnableMessage) |
||||
{ |
||||
SendMessage(MessageOnDeInit, SendMessageOptions.DontRequireReceiver); |
||||
} |
||||
} |
||||
|
||||
public virtual void OnObjectSpawn() |
||||
{ |
||||
if (EnableMessage) |
||||
{ |
||||
SendMessage(MessageOnSpawn, SendMessageOptions.DontRequireReceiver); |
||||
} |
||||
} |
||||
|
||||
public virtual void OnObjectDespawn() |
||||
{ |
||||
UsedTime = 0; |
||||
PrefabHash = 0; |
||||
|
||||
if (EnableMessage) |
||||
{ |
||||
SendMessage(MessageOnDespawn, SendMessageOptions.DontRequireReceiver); |
||||
} |
||||
} |
||||
|
||||
public virtual void OnObjectUpdate(float deltaTime) |
||||
{ |
||||
UsedTime += deltaTime; |
||||
} |
||||
|
||||
public bool DespawnSelf() |
||||
{ |
||||
return Pool.DespawnObject(this); |
||||
} |
||||
} |
||||
|
||||
|
||||
public static class RecyclableMonoBehaviourExt |
||||
{ |
||||
public static RecyclableMonoBehaviour GetOrCreateRecyclableMono(this GameObject gameObj, |
||||
bool enableMessage = false) |
||||
{ |
||||
Assert.IsNotNull(gameObj); |
||||
var recyclableMono = gameObj.GetComponent<RecyclableMonoBehaviour>(); |
||||
if (recyclableMono) |
||||
{ |
||||
return recyclableMono; |
||||
} |
||||
recyclableMono = gameObj.AddComponent<RecyclableMonoBehaviour>(); |
||||
recyclableMono.EnableMessage = enableMessage; |
||||
return recyclableMono; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: cc3dd3e8963f45f198d01d5e6664032e |
||||
timeCreated: 1735963499 |
@ -0,0 +1,387 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace Tools.EasyPoolKit |
||||
{ |
||||
public abstract class RecyclablePoolBase<T> : IRecyclablePool<T> where T : class, IRecyclable |
||||
{ |
||||
protected Queue<T> CachedQueue { get; private set; } |
||||
|
||||
protected LinkedList<T> UsedList { get; private set; } |
||||
|
||||
private int _objectCounter = 0; |
||||
|
||||
private bool _ifInit = false; |
||||
|
||||
public RecycleObjectType ObjectType { get; private set;} |
||||
public Type ReferenceType { get; private set;} |
||||
public string PoolId { get; private set;} |
||||
public int? InitCreateCount { get; private set;} |
||||
public int? MaxSpawnCount { get; private set;} |
||||
public int? MaxDespawnCount { get; private set;} |
||||
public float? AutoClearTime { get; private set;} |
||||
public Func<object> SpawnFunc { get; set; } |
||||
public PoolReachMaxLimitType ReachMaxLimitType { get; private set;} |
||||
public PoolDespawnDestroyType DespawnDestroyType { get; private set;} |
||||
public PoolClearType ClearType { get; private set;} |
||||
public bool IsIgnoreTimeScale { get; private set;} |
||||
|
||||
public int GetCachedObjectCount() => CachedQueue.Count; |
||||
public int GetUsedObjectCount() => UsedList.Count; |
||||
public int GetTotalObjectCount() => CachedQueue.Count + UsedList.Count; |
||||
|
||||
protected readonly RecyclablePoolInfo PoolInfo; |
||||
public RecyclablePoolInfo GetPoolInfoReadOnly() => PoolInfo; |
||||
|
||||
public RecyclablePoolBase(RecyclablePoolConfig config) |
||||
{ |
||||
PoolInfo = InitByConfig(config); |
||||
} |
||||
|
||||
protected virtual RecyclablePoolInfo InitByConfig(RecyclablePoolConfig config) |
||||
{ |
||||
if (_ifInit) |
||||
{ |
||||
throw new Exception("EasyEventPool == Already Init!"); |
||||
} |
||||
|
||||
if (config == null) |
||||
{ |
||||
throw new Exception("EasyEventPool == config is null!"); |
||||
} |
||||
|
||||
ObjectType = config.ObjectType; |
||||
ReferenceType = config.ReferenceType; |
||||
PoolId = config.PoolId; |
||||
SpawnFunc = config.SpawnFunc ?? throw new Exception("EasyEventPool == config.SpawnFunc is null!"); |
||||
ReachMaxLimitType = config.ReachMaxLimitType; |
||||
DespawnDestroyType = config.DespawnDestroyType; |
||||
ClearType = config.ClearType; |
||||
InitCreateCount = config.InitCreateCount; |
||||
MaxSpawnCount = config.MaxSpawnCount; |
||||
MaxDespawnCount = config.MaxDespawnCount; |
||||
AutoClearTime = config.AutoClearTime; |
||||
IsIgnoreTimeScale = config.IsIgnoreTimeScale; |
||||
|
||||
var poolInfo = new RecyclablePoolInfo(config, GetCachedObjectCount, GetUsedObjectCount, GetTotalObjectCount, this); |
||||
|
||||
CachedQueue = MaxSpawnCount.HasValue |
||||
? new Queue<T>(MaxSpawnCount.Value + 1) |
||||
: new Queue<T>(); |
||||
|
||||
UsedList = new LinkedList<T>(); |
||||
OnInitByParams(config.ExtraArgs); |
||||
InitCachedPool(); |
||||
_ifInit = true; |
||||
|
||||
#if EASY_POOL_DEBUG |
||||
//Check if params are valid |
||||
if (ReachMaxLimitType == PoolReachMaxLimitType.RejectNull || |
||||
ReachMaxLimitType == PoolReachMaxLimitType.RecycleOldest) |
||||
{ |
||||
if (!(MaxSpawnCount.HasValue && MaxSpawnCount.Value > 0)) |
||||
{ |
||||
throw new Exception("MaxSpawnCount.Value should > 0"); |
||||
} |
||||
} |
||||
|
||||
if (DespawnDestroyType == PoolDespawnDestroyType.DestroyToLimit) |
||||
{ |
||||
if (!(MaxDespawnCount.HasValue && MaxDespawnCount.Value > 0)) |
||||
{ |
||||
throw new Exception("MaxDespawnCount.Value should > 0"); |
||||
} |
||||
} |
||||
|
||||
if (MaxSpawnCount.HasValue && MaxDespawnCount.HasValue) |
||||
{ |
||||
if (!(MaxDespawnCount.Value <= MaxSpawnCount.Value)) |
||||
{ |
||||
throw new Exception("MaxDespawnCount.Value should <= MaxSpawnCount.Value"); |
||||
} |
||||
} |
||||
|
||||
if (MaxSpawnCount.HasValue && InitCreateCount.HasValue) |
||||
{ |
||||
if (!(InitCreateCount.Value <= MaxSpawnCount.Value)) |
||||
{ |
||||
throw new Exception("InitCreateCount.Value should <= MaxSpawnCount.Value"); |
||||
} |
||||
} |
||||
#endif |
||||
return poolInfo; |
||||
} |
||||
|
||||
public T SpawnObject() |
||||
{ |
||||
T cachedObj = null; |
||||
|
||||
if (GetCachedObjectCount() > 0) |
||||
{ |
||||
cachedObj = CachedQueue.Dequeue(); |
||||
} |
||||
else |
||||
{ |
||||
bool ifReachLimit = false; |
||||
|
||||
if (ReachMaxLimitType != PoolReachMaxLimitType.Default && MaxSpawnCount.HasValue) |
||||
{ |
||||
ifReachLimit = GetTotalObjectCount() >= MaxSpawnCount.Value; |
||||
} |
||||
|
||||
if (!ifReachLimit) |
||||
{ |
||||
cachedObj = CreateObject(); |
||||
} |
||||
else |
||||
{ |
||||
switch (ReachMaxLimitType) |
||||
{ |
||||
case PoolReachMaxLimitType.RecycleOldest: |
||||
cachedObj = RecycleOldestObject(); |
||||
break; |
||||
case PoolReachMaxLimitType.Default: |
||||
//Impossible |
||||
case PoolReachMaxLimitType.RejectNull: |
||||
default: |
||||
//do nothing |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (cachedObj != null) |
||||
{ |
||||
OnObjectDequeue(cachedObj); |
||||
cachedObj.OnObjectSpawn(); |
||||
UsedList.AddLast(cachedObj); |
||||
} |
||||
|
||||
return cachedObj; |
||||
} |
||||
|
||||
public bool TrySpawnObject(out T newObj) |
||||
{ |
||||
newObj = SpawnObject(); |
||||
return newObj != null; |
||||
} |
||||
|
||||
public bool DespawnObject(T usedObj) |
||||
{ |
||||
if (usedObj == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
var usedNode = UsedList.Find(usedObj); |
||||
|
||||
if (usedNode == null) |
||||
{ |
||||
return false; |
||||
} |
||||
|
||||
bool ifReachLimit = false; |
||||
|
||||
if (DespawnDestroyType == PoolDespawnDestroyType.DestroyToLimit) |
||||
{ |
||||
if (MaxDespawnCount.HasValue && GetTotalObjectCount() > MaxDespawnCount.Value) |
||||
{ |
||||
ifReachLimit = true; |
||||
} |
||||
} |
||||
|
||||
UsedList.Remove(usedNode); |
||||
usedObj.OnObjectDespawn(); |
||||
|
||||
if (ifReachLimit) |
||||
{ |
||||
DestroyPoolObject(usedObj); |
||||
} |
||||
else |
||||
{ |
||||
CachedQueue.Enqueue(usedObj); |
||||
OnObjectEnqueue(usedObj); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public void OnPoolUpdate(float deltaTime) |
||||
{ |
||||
if (UsedList.Count > 0) |
||||
{ |
||||
var beginNode = UsedList.First; |
||||
float collectTime = AutoClearTime ?? -1f; |
||||
|
||||
while (beginNode != null) |
||||
{ |
||||
var currentNode = beginNode; |
||||
beginNode = beginNode.Next; |
||||
var usedObj = currentNode.Value; |
||||
usedObj.OnObjectUpdate(deltaTime); |
||||
|
||||
if (collectTime > 0 && usedObj.UsedTime >= collectTime) |
||||
{ |
||||
DespawnObject(usedObj); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void InitCachedPool() |
||||
{ |
||||
if (!InitCreateCount.HasValue) |
||||
{ |
||||
return; |
||||
} |
||||
|
||||
var initCount = InitCreateCount.Value; |
||||
|
||||
for (int i = 0; i < initCount; i++) |
||||
{ |
||||
var cachedObj = CreateObject(); |
||||
CachedQueue.Enqueue(cachedObj); |
||||
OnObjectEnqueue(cachedObj); |
||||
} |
||||
} |
||||
|
||||
|
||||
private T CreateObject() |
||||
{ |
||||
_objectCounter++; |
||||
|
||||
if (SpawnFunc?.Invoke() is T cachedObj) |
||||
{ |
||||
cachedObj.PoolId = PoolId; |
||||
cachedObj.ObjectId = _objectCounter; |
||||
|
||||
#if EASY_POOL_DEBUG |
||||
cachedObj.Name = $"{PoolId}_{cachedObj.ObjectId}"; |
||||
#endif |
||||
OnObjectInit(cachedObj); |
||||
cachedObj.OnObjectInit(); |
||||
} |
||||
#if EASY_POOL_DEBUG |
||||
else |
||||
{ |
||||
throw new Exception($"EasyPoolKit == GenerateObject {PoolId} Should not be null!"); |
||||
} |
||||
#endif |
||||
|
||||
return cachedObj; |
||||
} |
||||
|
||||
protected virtual void OnInitByParams(object[] args){} |
||||
protected abstract void OnObjectInit(T usedObj); |
||||
protected abstract void OnObjectEnqueue(T usedObj); |
||||
protected abstract void OnObjectDequeue(T usedObj); |
||||
protected abstract void OnObjectDestoryInit(T usedObj); |
||||
|
||||
private T RecycleOldestObject() |
||||
{ |
||||
var firstNode = UsedList.First; |
||||
UsedList.Remove(firstNode); |
||||
var oldestObj = firstNode.Value; |
||||
|
||||
if (oldestObj != null) |
||||
{ |
||||
oldestObj.OnObjectDespawn(); |
||||
} |
||||
|
||||
//As it is a free node, need not to add it to cachedQueue |
||||
return oldestObj; |
||||
} |
||||
|
||||
private void DestroyPoolObject(T poolObj) |
||||
{ |
||||
if (poolObj != null) |
||||
{ |
||||
poolObj.OnObjectDestroyInit(); |
||||
OnObjectDestoryInit(poolObj); |
||||
} |
||||
} |
||||
|
||||
#region Clear |
||||
|
||||
public void ClearUnusedObjects() |
||||
{ |
||||
foreach (var cachedItem in CachedQueue) |
||||
{ |
||||
DestroyPoolObject(cachedItem); |
||||
} |
||||
|
||||
CachedQueue.Clear(); |
||||
} |
||||
|
||||
public void ClearAll() |
||||
{ |
||||
switch (ClearType) |
||||
{ |
||||
case PoolClearType.Default: |
||||
poolClearAll(); |
||||
break; |
||||
case PoolClearType.ClearToLimit: |
||||
poolClearToLimit(); |
||||
break; |
||||
} |
||||
|
||||
void poolClearAll() |
||||
{ |
||||
foreach (var cachedItem in CachedQueue) |
||||
{ |
||||
DestroyPoolObject(cachedItem); |
||||
} |
||||
|
||||
CachedQueue.Clear(); |
||||
|
||||
while (UsedList.Count > 0) |
||||
{ |
||||
var firstNode = UsedList.First; |
||||
var firstObj = firstNode.Value; |
||||
UsedList.Remove(firstNode); |
||||
DestroyPoolObject(firstObj); |
||||
} |
||||
|
||||
UsedList.Clear(); |
||||
} |
||||
|
||||
void poolClearToLimit() |
||||
{ |
||||
if (!InitCreateCount.HasValue) |
||||
{ |
||||
poolClearAll(); |
||||
return; |
||||
} |
||||
|
||||
poolClearRetain(); |
||||
|
||||
int removeCount = GetCachedObjectCount() - InitCreateCount.Value; |
||||
|
||||
while (removeCount > 0) |
||||
{ |
||||
removeCount--; |
||||
var cachedObj = CachedQueue.Dequeue(); |
||||
DestroyPoolObject(cachedObj); |
||||
} |
||||
|
||||
// 回收正在使用的物体 |
||||
void poolClearRetain() |
||||
{ |
||||
while (UsedList.Count > 0) |
||||
{ |
||||
var firstNode = UsedList.First; |
||||
var firstObj = firstNode.Value; |
||||
DespawnObject(firstObj); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
#region Debug |
||||
public string GetDebugConfigInfo() => PoolInfo?.GetDebugConfigInfo() ?? string.Empty; |
||||
public string GetDebugRunningInfo() => PoolInfo?.GetDebugRunningInfo() ?? string.Empty; |
||||
#endregion |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 2f64392ce63446c280cd10dee37231e8 |
||||
timeCreated: 1735964418 |
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 259a517e8654b99499c0f17a15beb06f |
||||
folderAsset: yes |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,274 @@
|
||||
%YAML 1.1 |
||||
%TAG !u! tag:unity3d.com,2011: |
||||
--- !u!1 &212430069314405427 |
||||
GameObject: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
serializedVersion: 6 |
||||
m_Component: |
||||
- component: {fileID: 5249829104186841453} |
||||
- component: {fileID: 8202632885764616307} |
||||
- component: {fileID: 7186356064517121775} |
||||
m_Layer: 5 |
||||
m_Name: Text (TMP) |
||||
m_TagString: Untagged |
||||
m_Icon: {fileID: 0} |
||||
m_NavMeshLayer: 0 |
||||
m_StaticEditorFlags: 0 |
||||
m_IsActive: 1 |
||||
--- !u!224 &5249829104186841453 |
||||
RectTransform: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 212430069314405427} |
||||
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_ConstrainProportionsScale: 0 |
||||
m_Children: [] |
||||
m_Father: {fileID: 6440907175184653233} |
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
||||
m_AnchorMin: {x: 0, y: 0} |
||||
m_AnchorMax: {x: 1, y: 1} |
||||
m_AnchoredPosition: {x: 0, y: 0} |
||||
m_SizeDelta: {x: 0, y: 0} |
||||
m_Pivot: {x: 0.5, y: 0.5} |
||||
--- !u!222 &8202632885764616307 |
||||
CanvasRenderer: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 212430069314405427} |
||||
m_CullTransparentMesh: 1 |
||||
--- !u!114 &7186356064517121775 |
||||
MonoBehaviour: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 212430069314405427} |
||||
m_Enabled: 1 |
||||
m_EditorHideFlags: 0 |
||||
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} |
||||
m_Name: |
||||
m_EditorClassIdentifier: |
||||
m_Material: {fileID: 0} |
||||
m_Color: {r: 1, g: 1, b: 1, a: 1} |
||||
m_RaycastTarget: 1 |
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} |
||||
m_Maskable: 1 |
||||
m_OnCullStateChanged: |
||||
m_PersistentCalls: |
||||
m_Calls: [] |
||||
m_text: Button |
||||
m_isRightToLeft: 0 |
||||
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} |
||||
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2} |
||||
m_fontSharedMaterials: [] |
||||
m_fontMaterial: {fileID: 0} |
||||
m_fontMaterials: [] |
||||
m_fontColor32: |
||||
serializedVersion: 2 |
||||
rgba: 4281479730 |
||||
m_fontColor: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} |
||||
m_enableVertexGradient: 0 |
||||
m_colorMode: 3 |
||||
m_fontColorGradient: |
||||
topLeft: {r: 1, g: 1, b: 1, a: 1} |
||||
topRight: {r: 1, g: 1, b: 1, a: 1} |
||||
bottomLeft: {r: 1, g: 1, b: 1, a: 1} |
||||
bottomRight: {r: 1, g: 1, b: 1, a: 1} |
||||
m_fontColorGradientPreset: {fileID: 0} |
||||
m_spriteAsset: {fileID: 0} |
||||
m_tintAllSprites: 0 |
||||
m_StyleSheet: {fileID: 0} |
||||
m_TextStyleHashCode: -1183493901 |
||||
m_overrideHtmlColors: 0 |
||||
m_faceColor: |
||||
serializedVersion: 2 |
||||
rgba: 4294967295 |
||||
m_fontSize: 24 |
||||
m_fontSizeBase: 24 |
||||
m_fontWeight: 400 |
||||
m_enableAutoSizing: 0 |
||||
m_fontSizeMin: 18 |
||||
m_fontSizeMax: 72 |
||||
m_fontStyle: 0 |
||||
m_HorizontalAlignment: 2 |
||||
m_VerticalAlignment: 512 |
||||
m_textAlignment: 65535 |
||||
m_characterSpacing: 0 |
||||
m_wordSpacing: 0 |
||||
m_lineSpacing: 0 |
||||
m_lineSpacingMax: 0 |
||||
m_paragraphSpacing: 0 |
||||
m_charWidthMaxAdj: 0 |
||||
m_TextWrappingMode: 1 |
||||
m_wordWrappingRatios: 0.4 |
||||
m_overflowMode: 0 |
||||
m_linkedTextComponent: {fileID: 0} |
||||
parentLinkedComponent: {fileID: 0} |
||||
m_enableKerning: 0 |
||||
m_ActiveFontFeatures: 6e72656b |
||||
m_enableExtraPadding: 0 |
||||
checkPaddingRequired: 0 |
||||
m_isRichText: 1 |
||||
m_EmojiFallbackSupport: 1 |
||||
m_parseCtrlCharacters: 1 |
||||
m_isOrthographic: 1 |
||||
m_isCullingEnabled: 0 |
||||
m_horizontalMapping: 0 |
||||
m_verticalMapping: 0 |
||||
m_uvLineOffset: 0 |
||||
m_geometrySortingOrder: 0 |
||||
m_IsTextObjectScaleStatic: 0 |
||||
m_VertexBufferAutoSizeReduction: 0 |
||||
m_useMaxVisibleDescender: 1 |
||||
m_pageToDisplay: 1 |
||||
m_margin: {x: 0, y: 0, z: 0, w: 0} |
||||
m_isUsingLegacyAnimationComponent: 0 |
||||
m_isVolumetricText: 0 |
||||
m_hasFontAssetChanged: 0 |
||||
m_baseMaterial: {fileID: 0} |
||||
m_maskOffset: {x: 0, y: 0, z: 0, w: 0} |
||||
--- !u!1 &5635780241963879440 |
||||
GameObject: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
serializedVersion: 6 |
||||
m_Component: |
||||
- component: {fileID: 6440907175184653233} |
||||
- component: {fileID: 3201388121702467737} |
||||
- component: {fileID: 4180124986893198757} |
||||
- component: {fileID: 54520249064627873} |
||||
- component: {fileID: -7838970888251817805} |
||||
m_Layer: 5 |
||||
m_Name: Button |
||||
m_TagString: Untagged |
||||
m_Icon: {fileID: 0} |
||||
m_NavMeshLayer: 0 |
||||
m_StaticEditorFlags: 0 |
||||
m_IsActive: 1 |
||||
--- !u!224 &6440907175184653233 |
||||
RectTransform: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 5635780241963879440} |
||||
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_ConstrainProportionsScale: 0 |
||||
m_Children: |
||||
- {fileID: 5249829104186841453} |
||||
m_Father: {fileID: 0} |
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} |
||||
m_AnchorMin: {x: 0, y: 1} |
||||
m_AnchorMax: {x: 0, y: 1} |
||||
m_AnchoredPosition: {x: 91.5, y: -15} |
||||
m_SizeDelta: {x: 183, y: 30} |
||||
m_Pivot: {x: 0.5, y: 0.5} |
||||
--- !u!222 &3201388121702467737 |
||||
CanvasRenderer: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 5635780241963879440} |
||||
m_CullTransparentMesh: 1 |
||||
--- !u!114 &4180124986893198757 |
||||
MonoBehaviour: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 5635780241963879440} |
||||
m_Enabled: 1 |
||||
m_EditorHideFlags: 0 |
||||
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} |
||||
m_Name: |
||||
m_EditorClassIdentifier: |
||||
m_Material: {fileID: 0} |
||||
m_Color: {r: 1, g: 1, b: 1, a: 1} |
||||
m_RaycastTarget: 1 |
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} |
||||
m_Maskable: 1 |
||||
m_OnCullStateChanged: |
||||
m_PersistentCalls: |
||||
m_Calls: [] |
||||
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0} |
||||
m_Type: 1 |
||||
m_PreserveAspect: 0 |
||||
m_FillCenter: 1 |
||||
m_FillMethod: 4 |
||||
m_FillAmount: 1 |
||||
m_FillClockwise: 1 |
||||
m_FillOrigin: 0 |
||||
m_UseSpriteMesh: 0 |
||||
m_PixelsPerUnitMultiplier: 1 |
||||
--- !u!114 &54520249064627873 |
||||
MonoBehaviour: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 5635780241963879440} |
||||
m_Enabled: 1 |
||||
m_EditorHideFlags: 0 |
||||
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} |
||||
m_Name: |
||||
m_EditorClassIdentifier: |
||||
m_Navigation: |
||||
m_Mode: 3 |
||||
m_WrapAround: 0 |
||||
m_SelectOnUp: {fileID: 0} |
||||
m_SelectOnDown: {fileID: 0} |
||||
m_SelectOnLeft: {fileID: 0} |
||||
m_SelectOnRight: {fileID: 0} |
||||
m_Transition: 1 |
||||
m_Colors: |
||||
m_NormalColor: {r: 1, g: 1, b: 1, a: 1} |
||||
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} |
||||
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} |
||||
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} |
||||
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} |
||||
m_ColorMultiplier: 1 |
||||
m_FadeDuration: 0.1 |
||||
m_SpriteState: |
||||
m_HighlightedSprite: {fileID: 0} |
||||
m_PressedSprite: {fileID: 0} |
||||
m_SelectedSprite: {fileID: 0} |
||||
m_DisabledSprite: {fileID: 0} |
||||
m_AnimationTriggers: |
||||
m_NormalTrigger: Normal |
||||
m_HighlightedTrigger: Highlighted |
||||
m_PressedTrigger: Pressed |
||||
m_SelectedTrigger: Selected |
||||
m_DisabledTrigger: Disabled |
||||
m_Interactable: 1 |
||||
m_TargetGraphic: {fileID: 4180124986893198757} |
||||
m_OnClick: |
||||
m_PersistentCalls: |
||||
m_Calls: [] |
||||
--- !u!114 &-7838970888251817805 |
||||
MonoBehaviour: |
||||
m_ObjectHideFlags: 0 |
||||
m_CorrespondingSourceObject: {fileID: 0} |
||||
m_PrefabInstance: {fileID: 0} |
||||
m_PrefabAsset: {fileID: 0} |
||||
m_GameObject: {fileID: 5635780241963879440} |
||||
m_Enabled: 1 |
||||
m_EditorHideFlags: 0 |
||||
m_Script: {fileID: 11500000, guid: 74056c96f6b34045924a42030d0ba1f9, type: 3} |
||||
m_Name: |
||||
m_EditorClassIdentifier: |
||||
EnableMessage: 0 |
||||
button: {fileID: 54520249064627873} |
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 42fa37d0d62c2c649ad2a46cd6042baa |
||||
PrefabImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,33 @@
|
||||
using UnityEngine; |
||||
using UnityEngine.UI; |
||||
|
||||
namespace Tools.EasyPoolKit.Demo |
||||
{ |
||||
public class ImageButton : RecyclableMonoBehaviour |
||||
{ |
||||
[SerializeField] private Button button; |
||||
|
||||
public override void OnObjectInit() |
||||
{ |
||||
base.OnObjectInit(); |
||||
button.onClick.AddListener(OnClick); |
||||
} |
||||
|
||||
public override void OnObjectSpawn() |
||||
{ |
||||
base.OnObjectSpawn(); |
||||
Debug.Log($"ImageButton Spawned {name}"); |
||||
} |
||||
|
||||
public override void OnObjectDespawn() |
||||
{ |
||||
base.OnObjectDespawn(); |
||||
Debug.Log($"ImageButton Despawn {name}"); |
||||
} |
||||
|
||||
private void OnClick() |
||||
{ |
||||
Debug.Log($"Button Clicked {name}"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 74056c96f6b34045924a42030d0ba1f9 |
||||
timeCreated: 1735967055 |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2 |
||||
guid: 5f9a4efcfd104ae42a4bd7e35bc1d016 |
||||
DefaultImporter: |
||||
externalObjects: {} |
||||
userData: |
||||
assetBundleName: |
||||
assetBundleVariant: |
@ -0,0 +1,56 @@
|
||||
using System; |
||||
using UnityEngine; |
||||
|
||||
namespace Tools.EasyPoolKit.Demo |
||||
{ |
||||
public class RecyclableGOPoolManager : MonoBehaviour |
||||
{ |
||||
[SerializeField] private GameObject buttonPrefab; |
||||
|
||||
[SerializeField] private Transform parent; |
||||
|
||||
private void Awake() |
||||
{ |
||||
var buttonConfig = new RecyclablePoolConfig() |
||||
{ |
||||
ObjectType = RecycleObjectType.RecyclableGameObject, |
||||
ReferenceType = typeof(ImageButton), |
||||
PoolId = "ImageButtonPool", |
||||
InitCreateCount = 5, |
||||
ReachMaxLimitType = PoolReachMaxLimitType.RecycleOldest, |
||||
MaxSpawnCount = 10, |
||||
DespawnDestroyType = PoolDespawnDestroyType.DestroyToLimit, |
||||
MaxDespawnCount = 5, |
||||
ClearType = PoolClearType.ClearToLimit, |
||||
IsIgnoreTimeScale = false, |
||||
}; |
||||
RecyclableGOPoolKit.Instance.RegisterPrefab(buttonPrefab, buttonConfig); |
||||
} |
||||
|
||||
private void Update() |
||||
{ |
||||
if (Input.GetKeyDown(KeyCode.A)) |
||||
{ |
||||
var newImage = RecyclableGOPoolKit.Instance.SimpleSpawn<ImageButton>(buttonPrefab); |
||||
newImage.transform.SetParent(parent); |
||||
} |
||||
// else if (Input.GetKeyDown(KeyCode.S)) |
||||
// { |
||||
// RecyclableGOPoolKit.Instance.Despawn("Image"); |
||||
// } |
||||
// else if (Input.GetKeyDown(KeyCode.C)) |
||||
// { |
||||
// RecyclableGOPoolKit.Instance.ClearAllPools(true); |
||||
// } |
||||
// else if (Input.GetKeyDown(KeyCode.Alpha1)) |
||||
// { |
||||
// var newImage = RecyclableGOPoolKit.Instance.Spawn("Cube"); |
||||
// newImage.transform.SetParent(null); |
||||
// } |
||||
// else if (Input.GetKeyDown(KeyCode.Alpha2)) |
||||
// { |
||||
// RecyclableGOPoolKit.Instance.Despawn("Cube"); |
||||
// } |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue