优点:
避免了Instantiate()和Destroy(), 减少GC
缺点:
占用内存, GC无法回收
池子里有50个, 实际可能只用到了3个, 会浪费内存
注意: 从池子里取出来的时候, 一定一定一定要把初始化写全
对象池有很多种写法, 有的人用栈, 有的用列表, 我这里用的是字典
思路很简单:
用的时候从池子里取, 如果池子里没有, 则创建一个
回收的时候扔到池子里
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pool : MonoBehaviour
{
Dictionary<string, List<GameObject>> GoDic = new Dictionary<string, List<GameObject>>();
Dictionary<string, GameObject> PrefabDic = new Dictionary<string, GameObject>();
private static Pool instance;
static Transform GoPool;
public static Pool Instance
{
get
{
if (null == instance)
{
instance = FindObjectOfType<Pool>(); ;
if (null == instance)
{
GoPool = new GameObject("GoPool").transform;
instance = GoPool.gameObject.AddComponent<Pool>();
}
}
return instance;
}
}
public void Init()
{
//读取并保存,预制体字典和对象池
GameObject[] prefabs = Resources.LoadAll<GameObject>("Prefabs");
foreach (var item in prefabs)
{
if (!PrefabDic.ContainsKey(item.name))
{
PrefabDic.Add(item.name, item);
}
if (!GoDic.ContainsKey(item.name))
{
GoDic.Add(item.name, new List<GameObject>());
}
}
}
//从对象池中拿出一个
GameObject PoolPopGO(string key)
{
GameObject go;
if (GoDic.ContainsKey(key))
{
if (GoDic[key].Count > 0)
{
go = GoDic[key][0];
if (go.activeInHierarchy)
{
Debug.LogError("出错了哦, 为什么对象池里会有活物呢");
}
GoDic[key].Remove(go);
if (go == null)
{
Debug.LogError("出错了哦, 为什么对象池里会有空物体呢");
}
go.SetActive(true);
}
else
{
go = Instantiate(PrefabDic[key]);
go.name = key;
}
return go;
}
else { Debug.LogError("对象池中找不到: " + key + ", 无法创建"); }
return null;
}
/// <summary>
/// 得到一个物体
/// </summary>
public GameObject GetGo(string name)
{
GameObject result = PoolPopGO(name);
return result;
}
/// <summary>
/// 得到一个物体,并设置爸爸
/// </summary>
public GameObject GetGo(string name, Transform trs)
{
GameObject result = PoolPopGO(name);
result.transform.SetParent(trs);
return result;
}
/// <summary>
/// 得到一个物体,并设置位置
/// </summary>
public GameObject GetGo(string name, Vector3 pos)
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
return result;
}
/// <summary>
/// 得到一个物体,并设置位置, 爸爸
/// </summary>
public GameObject GetGo(string name, Vector3 pos, Transform trs)
{
GameObject result = PoolPopGO(name);
result.transform.SetParent(trs);
result.transform.position = pos;
return result;
}
/// <summary>
/// 得到一个物体,并设置位置和角度
/// </summary>
public GameObject GetGo(string name, Vector3 pos, Quaternion ros)
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
result.transform.rotation = ros;
return result;
}
/// <summary>
/// 得到一个物体,并设置位置, 朝向
/// </summary>
public GameObject GetGo(string name, Vector3 pos, Vector3 tar)
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
result.transform.LookAt(tar);
return result;
}
/// <summary>
/// 得到一个物体,并设置位置, 朝向, 爸爸
/// </summary>
public GameObject GetGo(string name, Vector3 pos, Quaternion ros, Transform trs)
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
result.transform.rotation = ros;
result.transform.parent = trs;
return result;
}
/// <summary>
/// 物体回收
/// </summary>
public void Recycle(Transform go)
{
if (GoDic.ContainsKey(go.name))
{
if (!GoDic[go.name].Contains(go.gameObject))
{
GoDic[go.name].Add(go.gameObject);
go.gameObject.SetActive(false);
go.position = Vector3.zero;
}
else//这里是个坑, 有时候会放进去2遍
{
Debug.LogError("出错了哦, 不能把一个东西往对象池里放2遍");
}
}
else { Debug.LogError("对象池中找不到: " + go.name + ", 无法回收"); }
}
}
改了一版, 用了泛型
移除了笨蛋Init()方法, 改为手动Add()
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pool : MonoBehaviour
{
Dictionary<string, List<GameObject>> GoDic = new Dictionary<string, List<GameObject>>();
Dictionary<string, GameObject> PrefabDic = new Dictionary<string, GameObject>();
private static Pool instance;
static Transform goPool;
public static Pool Instance
{
get
{
if (null == instance)
{
instance = FindObjectOfType<Pool>();
if (null == instance)
{
goPool = new GameObject("GoPool").transform;
instance = goPool.gameObject.AddComponent<Pool>();
DontDestroyOnLoad(goPool);
}
}
return instance;
}
}
public void Add(string path)
{
//读取并保存,预制体字典和对象池
GameObject prefab = Resources.Load<GameObject>(path);
if (!PrefabDic.ContainsKey(prefab.name))
{
PrefabDic.Add(prefab.name, prefab);
}
if (!GoDic.ContainsKey(prefab.name))
{
GoDic.Add(prefab.name, new List<GameObject>());
}
}
//从对象池中拿出一个
GameObject PoolPopGO(string key)
{
if (GoDic.ContainsKey(key))
{
GameObject go;
if (GoDic[key].Count > 0)
{
go = GoDic[key][0];
if (go.activeInHierarchy)
{
Debug.LogError("出错了哦, 为什么对象池里会有活物呢");
}
GoDic[key].Remove(go);
if (null == go)
{
Debug.LogError("出错了哦, 为什么对象池里会有空物体呢");
}
go.SetActive(true);
}
else
{
go = Instantiate(PrefabDic[key]);
go.name = key;
}
return go;
}
else
{
Debug.LogError("对象池中找不到: " + key + ", 无法创建");
return null;
}
}
/// <summary>
/// 得到一个物体
/// </summary>
public T GetGo<T>(string name) where T : Component
{
GameObject result = PoolPopGO(name);
return result.GetComponent<T>();
}
/// <summary>
/// 得到一个物体,并设置爸爸
/// </summary>
public T GetGo<T>(string name, Transform trs) where T : Component
{
GameObject result = PoolPopGO(name);
result.transform.SetParent(trs);
return result.GetComponent<T>();
}
/// <summary>
/// 得到一个物体,并设置位置
/// </summary>
public T GetGo<T>(string name, Vector3 pos) where T : Component
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
return result.GetComponent<T>();
}
/// <summary>
/// 得到一个物体,并设置位置, 爸爸
/// </summary>
public T GetGo<T>(string name, Vector3 pos, Transform trs) where T : Component
{
GameObject result = PoolPopGO(name);
result.transform.SetParent(trs);
result.transform.position = pos;
return result.GetComponent<T>();
}
/// <summary>
/// 得到一个物体,并设置位置和角度
/// </summary>
public T GetGo<T>(string name, Vector3 pos, Quaternion ros) where T : Component
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
result.transform.rotation = ros;
return result.GetComponent<T>();
}
/// <summary>
/// 得到一个物体,并设置位置, 朝向
/// </summary>
public T GetGo<T>(string name, Vector3 pos, Vector3 tar) where T : Component
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
result.transform.LookAt(tar);
return result.GetComponent<T>();
}
/// <summary>
/// 得到一个物体,并设置位置, 朝向, 爸爸
/// </summary>
public T GetGo<T>(string name, Vector3 pos, Quaternion ros, Transform trs) where T : Component
{
GameObject result = PoolPopGO(name);
result.transform.position = pos;
result.transform.rotation = ros;
result.transform.parent = trs;
return result.GetComponent<T>();
}
/// <summary>
/// 物体回收
/// </summary>
public void Recycle<T>(T go) where T : Component
{
if (GoDic.ContainsKey(go.name))
{
if (!GoDic[go.name].Contains(go.gameObject))
{
GoDic[go.name].Add(go.gameObject);
go.transform.SetParent(transform);
go.gameObject.SetActive(false);
go.transform.position = Vector3.zero;
}
else//这里是个坑, 有时候会放进去2遍
{
//Debug.Log("出错了哦, 不要把同一个对象往池里放2次: " + go.name);
}
}
else
{
Debug.LogError("无法回收, 对象池中找不到: " + go.name);
}
}
}