使用对象池的好处就是:不用每次都创建对象然后销毁在创建,比如子弹的发射,当创建好的子弹,可以在使用后保存到对象池里面,当用的时候直接从对象池中取即可。
频繁的创建和销毁耗性能。
先看使用方法
(这里有一个TimerEvnt脚本和一个单例脚本是我之前写的自定义定时器)
连接: 点我跳转 TimerEvent.cs
连接: 点我跳转单例博文
也可以自己把这个脚本写成单例 , 计时器那个只是我方便测试功能用的你也可以不用看
private void Awake()
{
//初始化两个池子 PoolType.TEST1和PoolType.TEST2
MgrPool.Instance.InitPool(PoolType.TEST1, new GameObject("TEST1"), 5);
MgrPool.Instance.InitPool(PoolType.TEST2, new GameObject("TEST2"), 5);
//这个定时器是我测试功能用的 你们可以不用看
TimerEvent timerEvent = new TimerEvent(10f, () =>
{
MgrPool.Instance.ClaerAll();
Debug.Log(" 10秒后清理所有池子 ");
});
timerEvent.Start();
}
//点击事件
public void OnClickBtn()
{
//点击后从PoolType.NULL池子取出一个
GameObject go = MgrPool.Instance.Get(PoolType.TEST1);
go.transform.SetParent(this.transform);
go.transform.position = Vector3.zero;
//1秒后回收
TimerEvent timerEvent = new TimerEvent(1f, () =>
{
MgrPool.Instance.Put(PoolType.TEST1, go);
});
timerEvent.Start();
}
using System;
using System.Collections.Generic;
using UnityEngine;
//*****************************自定义对象池类型 可单独创建一个脚本**************************************************************//
public enum PoolType
{
DEFAULT,
TEST1,
TEST2,
}
public class MgrPool : SingletonBase<MgrPool>
{
//所有池子的字典
private Dictionary<PoolType, Queue<GameObject>> _poolDic = new Dictionary<PoolType, Queue<GameObject>>();
//所有池子类型节点
private Dictionary<PoolType, Transform> _pathDic = new Dictionary<PoolType, Transform>();
//池子容量不够用时候默认扩充数量
private int _expansion = 5;
//把所有池子归到统一节点下
private Transform _poolTotal;
//是否统一管理池子节点
private bool _unifiedMgr = true;
/// <summary>
/// 初始化
/// </summary>
/// <param name="poolType">对象池类型</param>
/// <param name="gameObject">Obj</param>
/// <param name="cont">初始化大小</param>
public void InitPool(PoolType poolType, GameObject prefab, int count = 20)
{
//创建个MgrPool节点 把所有池子都归到这个节点下 方便管理
if (_poolTotal == null) _poolTotal = new GameObject("MgrPool").transform;
if (!_poolDic.ContainsKey(poolType))
{
if (_unifiedMgr)
{
//如果是新池子 创建一个节点
Transform parent = new GameObject("Pool_" + poolType.ToString()).transform;
parent.SetParent(_poolTotal);
_pathDic.Add(poolType, parent);
}
_poolDic.Add(poolType, new Queue<GameObject>());
CreatorItem(poolType, prefab, count);
}
else
{
throw new Exception(string.Format("该池子:'{0}'已存在,请勿重复初始化!", poolType));
}
}
/// <summary>
/// 从池子里取出
/// </summary>
/// <param name="poolType">池子类型</param>
/// <returns></returns>
public GameObject Get(PoolType poolType)
{
if (_poolDic.ContainsKey(poolType) && _poolDic[poolType].Count > 0)
{
Queue<GameObject> goQueue = _poolDic[poolType];
GameObject prefab = null;
//这里留一个扩充池子用
if (goQueue.Count > 1)
{
prefab = goQueue.Dequeue();
prefab.SetActive(true);
}
//这里如果池子空间只剩下一个 就扩容池子
if (prefab == null && goQueue.Count <= 1)
{
CreatorItem(poolType, goQueue.Peek(), _expansion);
return Get(poolType);
}
return prefab;
}
else
{
throw new Exception(string.Format("该池子:'{0}'不存在或已被清理,请先初始化!", poolType));
}
}
public void Put(PoolType poolType, GameObject prefab)
{
if (!_poolDic.ContainsKey(poolType))
{
if (prefab != null) Destroy(prefab);
//throw new Exception(string.Format("该池子:'{0}'不存在或已被清理,请先初始化!", poolType));
Debug.LogWarning("该池子:'" + poolType + "'不存在或已被清理,请先初始化!");
}
else
{
if (_unifiedMgr)
{
prefab.transform.SetParent(_pathDic[poolType]);
}
prefab.SetActive(false);
_poolDic[poolType].Enqueue(prefab);
}
}
/// <summary>
/// 创建池子预制
/// </summary>
/// <param name="poolType">池子类型</param>
/// <param name="go">预制</param>
/// <param name="count">多少个</param>
private void CreatorItem(PoolType poolType, GameObject go, int count)
{
if (!_poolDic.ContainsKey(poolType))
{
throw new Exception(string.Format("该池子:'{0}'不存在或已被清理,请先初始化!", poolType));
}
for (int i = 0; i < count; i++)
{
GameObject goItem = Instantiate(go, Vector3.zero, Quaternion.identity);
goItem.transform.SetParent(_unifiedMgr ? _pathDic[poolType] : _poolTotal);
goItem.name = go.name;
goItem.SetActive(false);
_poolDic[poolType].Enqueue(goItem);
}
}
/// <summary>
/// 清理池子
/// </summary>
/// <param name="poolType">池子类型</param>
public void Clear(PoolType poolType)
{
if (!_poolDic.ContainsKey(poolType))
{
throw new Exception(string.Format("该池子:'{0}'不存在或已被清理,请先初始化!", poolType));
}
else
{
if (_unifiedMgr)
{
Destroy(_pathDic[poolType].gameObject);
_pathDic.Remove(poolType);
}
else
{
foreach (GameObject poolItem in _poolDic[poolType])
{
Destroy(poolItem);
}
}
_poolDic[poolType].Clear();
_poolDic.Remove(poolType);
}
}
/// <summary>
/// 清理所有池子
/// </summary>
public void ClaerAll()
{
if (_unifiedMgr)
{
if (_poolTotal != null) Destroy(_poolTotal.gameObject);
_pathDic.Clear();
}
else
{
foreach (Queue<GameObject> queue in _poolDic.Values)
{
foreach (GameObject go in queue)
{
Destroy(go);
}
}
}
_poolDic.Clear();
}
}