229 lines
6.5 KiB
C#
229 lines
6.5 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace AibisDream.Utility
|
|
{
|
|
/// <summary>
|
|
/// 通用对象池管理器
|
|
/// </summary>
|
|
public class ObjectPool : MonoBehaviour
|
|
{
|
|
[System.Serializable]
|
|
public class PoolItem
|
|
{
|
|
public string tag;
|
|
public GameObject prefab;
|
|
public int size;
|
|
}
|
|
|
|
[Header("对象池配置")]
|
|
public List<PoolItem> poolItems = new List<PoolItem>();
|
|
|
|
private Dictionary<string, Queue<GameObject>> poolDictionary;
|
|
private Dictionary<string, GameObject> prefabDictionary;
|
|
|
|
private void Awake()
|
|
{
|
|
InitializePools();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化所有对象池
|
|
/// </summary>
|
|
private void InitializePools()
|
|
{
|
|
poolDictionary = new Dictionary<string, Queue<GameObject>>();
|
|
prefabDictionary = new Dictionary<string, GameObject>();
|
|
|
|
foreach (PoolItem item in poolItems)
|
|
{
|
|
Queue<GameObject> objectPool = new Queue<GameObject>();
|
|
|
|
for (int i = 0; i < item.size; i++)
|
|
{
|
|
GameObject obj = CreateNewObject(item.prefab, item.tag);
|
|
objectPool.Enqueue(obj);
|
|
}
|
|
|
|
poolDictionary.Add(item.tag, objectPool);
|
|
prefabDictionary.Add(item.tag, item.prefab);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建新对象
|
|
/// </summary>
|
|
private GameObject CreateNewObject(GameObject prefab, string tag)
|
|
{
|
|
GameObject obj = Instantiate(prefab);
|
|
obj.SetActive(false);
|
|
|
|
// 添加池化组件
|
|
PooledObject pooledObj = obj.GetComponent<PooledObject>();
|
|
if (pooledObj == null)
|
|
{
|
|
pooledObj = obj.AddComponent<PooledObject>();
|
|
}
|
|
pooledObj.poolTag = tag;
|
|
|
|
return obj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从对象池获取对象
|
|
/// </summary>
|
|
public GameObject GetFromPool(string tag, Vector3 position, Quaternion rotation)
|
|
{
|
|
if (!poolDictionary.ContainsKey(tag))
|
|
{
|
|
Debug.LogWarning($"对象池中不存在标签: {tag}");
|
|
return null;
|
|
}
|
|
|
|
Queue<GameObject> pool = poolDictionary[tag];
|
|
GameObject obj;
|
|
|
|
if (pool.Count > 0)
|
|
{
|
|
obj = pool.Dequeue();
|
|
}
|
|
else
|
|
{
|
|
// 如果池为空,创建新对象
|
|
obj = CreateNewObject(prefabDictionary[tag], tag);
|
|
}
|
|
|
|
obj.SetActive(true);
|
|
obj.transform.position = position;
|
|
obj.transform.rotation = rotation;
|
|
|
|
return obj;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从对象池获取对象(使用默认位置和旋转)
|
|
/// </summary>
|
|
public GameObject GetFromPool(string tag)
|
|
{
|
|
return GetFromPool(tag, Vector3.zero, Quaternion.identity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将对象返回池中
|
|
/// </summary>
|
|
public void ReturnToPool(GameObject obj)
|
|
{
|
|
PooledObject pooledObj = obj.GetComponent<PooledObject>();
|
|
if (pooledObj == null)
|
|
{
|
|
Debug.LogWarning("对象没有PooledObject组件,无法返回池中");
|
|
return;
|
|
}
|
|
|
|
string tag = pooledObj.poolTag;
|
|
if (!poolDictionary.ContainsKey(tag))
|
|
{
|
|
Debug.LogWarning($"对象池中不存在标签: {tag}");
|
|
return;
|
|
}
|
|
|
|
obj.SetActive(false);
|
|
poolDictionary[tag].Enqueue(obj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 延迟返回对象到池中
|
|
/// </summary>
|
|
public void ReturnToPool(GameObject obj, float delay)
|
|
{
|
|
StartCoroutine(ReturnToPoolCoroutine(obj, delay));
|
|
}
|
|
|
|
private System.Collections.IEnumerator ReturnToPoolCoroutine(GameObject obj, float delay)
|
|
{
|
|
yield return new WaitForSeconds(delay);
|
|
ReturnToPool(obj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清空指定对象池
|
|
/// </summary>
|
|
public void ClearPool(string tag)
|
|
{
|
|
if (!poolDictionary.ContainsKey(tag))
|
|
{
|
|
Debug.LogWarning($"对象池中不存在标签: {tag}");
|
|
return;
|
|
}
|
|
|
|
Queue<GameObject> pool = poolDictionary[tag];
|
|
while (pool.Count > 0)
|
|
{
|
|
GameObject obj = pool.Dequeue();
|
|
if (obj != null)
|
|
{
|
|
Destroy(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清空所有对象池
|
|
/// </summary>
|
|
public void ClearAllPools()
|
|
{
|
|
foreach (string tag in poolDictionary.Keys)
|
|
{
|
|
ClearPool(tag);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取池中对象数量
|
|
/// </summary>
|
|
public int GetPoolSize(string tag)
|
|
{
|
|
if (!poolDictionary.ContainsKey(tag))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return poolDictionary[tag].Count;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 预加载对象到池中
|
|
/// </summary>
|
|
public void PreloadObjects(string tag, int count)
|
|
{
|
|
if (!prefabDictionary.ContainsKey(tag))
|
|
{
|
|
Debug.LogWarning($"预制体字典中不存在标签: {tag}");
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
GameObject obj = CreateNewObject(prefabDictionary[tag], tag);
|
|
poolDictionary[tag].Enqueue(obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 池化对象组件
|
|
/// </summary>
|
|
public class PooledObject : MonoBehaviour
|
|
{
|
|
[HideInInspector]
|
|
public string poolTag;
|
|
|
|
private void OnDisable()
|
|
{
|
|
// 当对象被禁用时,自动返回池中
|
|
// 注意:这可能会导致问题,如果对象被手动禁用
|
|
// 建议在需要时手动调用ReturnToPool
|
|
}
|
|
}
|
|
}
|