fix:1
This commit is contained in:
302
Assets/Scripts/Core/PoolManager.cs
Normal file
302
Assets/Scripts/Core/PoolManager.cs
Normal file
@@ -0,0 +1,302 @@
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user