- 依赖于UniTask(访问Github)
- 依赖于Addressable资源管理(通过UPM安装)
using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace EasyAVG
{
public class Pool
{
public Action<GameObject> OnGet { get; set; } = defaultGet;
public Action<GameObject> OnSet { get; set; } = defaultSet;
public Action<GameObject> OnDestroy { get; set; } = defaultDestroy;
public Action<GameObject> OnCreate { get; set; } = null;
public int MaxCount { get; set; } = int.MaxValue;
public int MinCount { get; set; } = 0;
public string Location { get; set; } = null;
private Queue<GameObject> queue = new Queue<GameObject>();
static readonly Action<GameObject> defaultGet = (x) =>
{
x.SetActive(true);
}
, defaultSet = (x) =>
{
x.SetActive(false);
}
, defaultDestroy = (x) =>
{
GameObject.Destroy(x);
};
internal bool _destroyed = false;
private IEnumerator PoolThread()
{
while (true)
{
if (_destroyed)
{
yield break;
}
if (MinCount > MaxCount) throw new InvalidOperationException($"Please keep MaxCount>MinCount . CurrentMin{MinCount}>CurreentMax{MaxCount}");
if (queue.Count < MinCount)
{
var handle = Addressables.InstantiateAsync(Location);
yield return handle;
OnCreate?.Invoke(handle.Result);
queue.Enqueue(handle.Result);
}
if (queue.Count > MaxCount)
{
OnDestroy?.Invoke(queue.Dequeue());
}
yield return null;
}
}
internal void InitPool()
{
PoolManager.Instance.StartCoroutine(PoolThread());
}
public async UniTask<GameObject> Get()
{
if (queue.Count == 0)
{
var handle = Addressables.InstantiateAsync(Location);
await handle;
OnCreate?.Invoke(handle.Result);
OnGet?.Invoke(handle.Result);
return handle.Result;
}
await UniTask.CompletedTask;
var item = queue.Dequeue();
OnGet?.Invoke(item);
return item;
}
public GameObject GetSync()
{
if (queue.Count == 0)
{
var handle = Addressables.InstantiateAsync(Location);
OnCreate?.Invoke(handle.Result);
OnGet?.Invoke(handle.Result);
return handle.Result;
}
var item = queue.Dequeue();
OnGet?.Invoke(item);
return item;
}
public void Set(GameObject item)
{
if (queue.Count >= MaxCount)
{
OnSet?.Invoke(item);
OnDestroy?.Invoke(item);
return;
}
else
{
OnSet?.Invoke(item);
queue.Enqueue(item);
}
}
}
}

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
using Cysharp.Threading.Tasks;
using EasyAVG;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace EasyAVG
{
public class PoolManager :MonoSingleton<PoolManager>
{
void OnDestroy()
{
foreach (var kvp in pools)
{
kvp.Value._destroyed = true;
}
pools.Clear();
}
private readonly Dictionary<string, Pool> pools = new Dictionary<string, Pool>();
public void CreatePool(string key, string location, int minCount = 0, int maxCount = int.MaxValue
)
{
if (pools.ContainsKey(key)) return;
Pool pool = new Pool();
pool.Location = location;
pool.MinCount = minCount;
pool.MaxCount = maxCount;
pools.Add(key, pool);
pool.InitPool();
}
public Pool GetPool(string key)
{
if (!pools.ContainsKey(key)) return null;
return pools[key];
}
public void DestroyPool(string key, bool exThrow = false)
{
if (!pools.ContainsKey(key))
{
if (exThrow)
throw new NullReferenceException("Destroying non-existent pool is not allowed");
else return;
}
pools[key]._destroyed = true;
pools.Remove(key);
}
public UniTask<GameObject> GetAsync(string key)
{
var pool = GetPool(key) ?? throw new InvalidOperationException("Please get after create pool");
return pool.Get();
}
public GameObject GetSync(string key)
{
var pool = GetPool(key) ?? throw new InvalidOperationException("Please get after create pool");
return pool.GetSync();
}
public void Recycle(string key, GameObject obj)
{
var pool = GetPool(key) ?? throw new InvalidOperationException("Please set after create pool");
pool.Set(obj);
}
public async UniTask<T> GetComponentAsync<T>(string key) where T : Component
{
var pool = GetPool(key);
return (await pool.Get()).GetComponent<T>();
}
public T GetComponentSync<T>(string key) where T : Component
{
var pool = GetPool(key);
return pool.GetSync().GetComponent<T>();
}
public void RecycleComponent<T>(string key, T com) where T : Component
{
var pool = GetPool(key);
pool.Set(com.gameObject);
}
}
}

- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155