302 lines
8.0 KiB
C#
302 lines
8.0 KiB
C#
using UnityEngine;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
|
||
/// <summary>
|
||
/// 对象池管理类,日常使用一下两个方法即可
|
||
/// 取对象Spawn(name/Prefab),回收对象Unspawn(name/Prefab)
|
||
/// </summary>
|
||
public class PoolManager : MonoBehaviour
|
||
{
|
||
private static readonly object lockObj = new object();
|
||
|
||
private static PoolManager _instance;
|
||
|
||
public static PoolManager Instance
|
||
{
|
||
get
|
||
{
|
||
if (_instance == null)
|
||
{
|
||
lock (lockObj)
|
||
{
|
||
PoolManager[] objs = FindObjectsOfType<PoolManager>();
|
||
if (objs != null)
|
||
{
|
||
for (int i = 0; i < objs.Length; i++)
|
||
{
|
||
DestroyImmediate(objs[i].gameObject);
|
||
}
|
||
}
|
||
GameObject go = new GameObject("PoolManager");
|
||
DontDestroyOnLoad(go);
|
||
_instance = go.AddComponent<PoolManager>();
|
||
}
|
||
}
|
||
return _instance;
|
||
}
|
||
}
|
||
|
||
//预制ID-对象池 集合
|
||
private Dictionary<int, ObjectPool> poolDic = new Dictionary<int, ObjectPool>();
|
||
//对象ID-对象池ID 集合
|
||
private Dictionary<int, int> itemDic = new Dictionary<int, int>();
|
||
|
||
|
||
/// <summary>
|
||
/// 取对象,通过对象实例
|
||
/// </summary>
|
||
public GameObject Spawn(GameObject prefab)
|
||
{
|
||
if (!poolDic.ContainsKey(prefab.GetInstanceID()))
|
||
{
|
||
CreateNewPool(prefab);
|
||
}
|
||
GameObject item = poolDic[prefab.GetInstanceID()].Spawn();
|
||
if (!itemDic.ContainsKey(item.GetInstanceID()))
|
||
{
|
||
itemDic.Add(item.GetInstanceID(), prefab.GetInstanceID());
|
||
}
|
||
else
|
||
{
|
||
itemDic[item.GetInstanceID()] = prefab.GetInstanceID();
|
||
}
|
||
return item;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收对象
|
||
/// </summary>
|
||
public void Unspawn(GameObject go)
|
||
{
|
||
if (itemDic.ContainsKey(go.GetInstanceID()))
|
||
{
|
||
int id = itemDic[go.GetInstanceID()];
|
||
if (poolDic.ContainsKey(id))
|
||
{
|
||
poolDic[id].Unspawn(go);
|
||
itemDic.Remove(go.GetInstanceID());
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("回收对象失败 : " + go.name);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收某个对象池中所有对象
|
||
/// </summary>
|
||
public void ClearPool(GameObject prefab)
|
||
{
|
||
int id = prefab.GetInstanceID();
|
||
if (poolDic.ContainsKey(id))
|
||
{
|
||
poolDic[id].UnspawnAll();
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("清空对象池失败 : " + prefab.name);
|
||
}
|
||
|
||
List<int> list = new List<int>();
|
||
foreach (int key in itemDic.Keys)
|
||
{
|
||
if (itemDic[key] == id)
|
||
{
|
||
list.Add(key);
|
||
}
|
||
}
|
||
for (int i = 0; i < list.Count; i++)
|
||
{
|
||
itemDic.Remove(list[i]);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收所有对象池
|
||
/// </summary>
|
||
public void ClearAll()
|
||
{
|
||
foreach (ObjectPool pool in poolDic.Values)
|
||
{
|
||
pool.UnspawnAll();
|
||
}
|
||
itemDic.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一个新的对象池
|
||
/// </summary>
|
||
public void CreateNewPool(GameObject prefab)
|
||
{
|
||
if (poolDic.ContainsKey(prefab.GetInstanceID()))
|
||
{
|
||
Debug.LogError("无法创建新的对象池,当前对象池已存在 : " + prefab.name);
|
||
return;
|
||
}
|
||
ObjectPool pool = new ObjectPool(prefab);
|
||
poolDic.Add(prefab.GetInstanceID(), pool);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一个新的对象池,并初始化
|
||
/// </summary>
|
||
public void CreateNewPool(GameObject prefab, int initSize)
|
||
{
|
||
if (poolDic.ContainsKey(prefab.GetInstanceID()))
|
||
{
|
||
Debug.LogError("无法创建新的对象池,当前对象池已存在 : " + prefab.name);
|
||
return;
|
||
}
|
||
ObjectPool pool = new ObjectPool(prefab);
|
||
pool.InitPool(initSize);
|
||
poolDic.Add(prefab.GetInstanceID(), pool);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一个新的对象池,并初始化,同时设定对象池最大容量
|
||
/// </summary>
|
||
public void CreateNewPool(GameObject prefab, int initSize, int maxSize)
|
||
{
|
||
if (poolDic.ContainsKey(prefab.GetInstanceID()))
|
||
{
|
||
Debug.LogError("无法创建新的对象池,当前对象池已存在 : " + prefab.name);
|
||
return;
|
||
}
|
||
ObjectPool pool = new ObjectPool(prefab, maxSize);
|
||
pool.InitPool(initSize);
|
||
poolDic.Add(prefab.GetInstanceID(), pool);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 对象池-子池
|
||
/// </summary>
|
||
public class ObjectPool
|
||
{
|
||
//对象池元素
|
||
public GameObject prefab;
|
||
|
||
//对象池最大容量,此值小于等于0时,对象池动态增加,不设上限
|
||
private int maxSize;
|
||
|
||
//对象池名称
|
||
public string Name
|
||
{
|
||
get { return prefab.name; }
|
||
}
|
||
|
||
//对象池当前容量
|
||
private int CurrentSize
|
||
{
|
||
get { return activeObjectList.Count + inactiveObjectList.Count; }
|
||
}
|
||
|
||
private List<GameObject> activeObjectList = new List<GameObject>(); //已用对象列表
|
||
private List<GameObject> inactiveObjectList = new List<GameObject>(); //待用对象列表
|
||
|
||
public ObjectPool(GameObject obj)
|
||
{
|
||
this.prefab = obj;
|
||
maxSize = -1;
|
||
}
|
||
|
||
public ObjectPool(GameObject obj, int maxCount)
|
||
{
|
||
this.prefab = obj;
|
||
maxSize = maxCount;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化对象池
|
||
/// </summary>
|
||
public void InitPool(int initSize)
|
||
{
|
||
if (maxSize > 0 && initSize > maxSize)
|
||
{
|
||
Debug.LogError("对象池初始容量不能超过其最大容量!!");
|
||
for (int i = 0; i < maxSize; i++)
|
||
{
|
||
GameObject go = GameObject.Instantiate(prefab);
|
||
go.name = prefab.name;
|
||
go.SetActive(false);
|
||
inactiveObjectList.Add(go);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (int i = 0; i < initSize; i++)
|
||
{
|
||
GameObject go = GameObject.Instantiate(prefab);
|
||
go.name = prefab.name;
|
||
go.SetActive(false);
|
||
inactiveObjectList.Add(go);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取对象
|
||
/// </summary>
|
||
public GameObject Spawn()
|
||
{
|
||
if (inactiveObjectList.Count == 0)
|
||
{
|
||
if (maxSize > 0 && CurrentSize >= maxSize)
|
||
{
|
||
Debug.LogError("警告:对象池 " + Name + " 当前容量已达到最大设定值 : " + maxSize);
|
||
GameObject go = activeObjectList[0];
|
||
return go;
|
||
}
|
||
else
|
||
{
|
||
GameObject go = GameObject.Instantiate(prefab);
|
||
go.SetActive(true);
|
||
activeObjectList.Add(go);
|
||
return go;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
GameObject go = inactiveObjectList[0];
|
||
go.SetActive(true);
|
||
inactiveObjectList.RemoveAt(0);
|
||
activeObjectList.Add(go);
|
||
return go;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收对象
|
||
/// </summary>
|
||
public void Unspawn(GameObject go)
|
||
{
|
||
if (activeObjectList.Contains(go))
|
||
{
|
||
go.SetActive(false);
|
||
activeObjectList.Remove(go);
|
||
inactiveObjectList.Add(go);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("回收对象异常,当前对象不在对象列表中!!");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收池中所有对象
|
||
/// </summary>
|
||
public void UnspawnAll()
|
||
{
|
||
//回收修改
|
||
int count = activeObjectList.Count;
|
||
for (int i = 0; i < count; i++)
|
||
{
|
||
if (activeObjectList.Count >= 1)
|
||
{
|
||
Unspawn(activeObjectList[0]);
|
||
}
|
||
}
|
||
}
|
||
} |