Files
2025-09-01 21:25:54 +08:00

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
}
}
}