using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour
{
//自身单例
public static ObjectPool me;
public Transform recovery;
//池的存储
//TODO 此处value使用自定义封装类型而不是单纯的queue更健全
private Dictionary<string, Queue<GameObject>> pool;
//每个池中最大数量
//TODO 应该每个池设置每个池单独的数量
private int maxCount = int.MaxValue;
public int MaxCount
{
get { return maxCount; }
set
{
maxCount = Mathf.Clamp(value, 0, int.MaxValue);
}
}
//初始化
void Awake()
{
me = this;
pool = new Dictionary<string, Queue<GameObject>>();
Debug.Log(MaxCount);
}
/// <summary>
/// 从池中获取物体
/// </summary>
/// <param name="go">需要取得的物体</param>
/// <param name="position"></param>
/// <param name="rotation"></param>
/// <returns></returns>
public GameObject GetObject(GameObject go, Vector3 position, Quaternion rotation)
{
//如果未初始化过 初始化池
if (!pool.ContainsKey(go.name))
{
pool.Add(go.name, new Queue<GameObject>());
}
//如果池空了就创建新物体
if (pool[go.name].Count == 0)
{
//GameObject newObject = Instantiate(go, position, rotation);
//newObject.name = go.name;/*
//确认名字一样,防止系统加一个(clone),或序号累加之类的
//实际上为了更健全可以给每一个物体加一个key,防止对象的name一样但实际上不同
// */
//return newObject;
Preload(go, 5);
}
//从池中获取物体
GameObject nextObject = pool[go.name].Dequeue();
nextObject.SetActive(true);//要先启动再设置属性,否则可能会被OnEnable重置
nextObject.transform.position = position;
nextObject.transform.rotation = rotation;
return nextObject;
}
/// <summary>
/// 把物体放回池里
/// </summary>
/// <param name="go">需要放回队列的物品</param>
/// <param name="t">延迟执行的时间</param>
/// TODO 应该做个检查put的gameobject的池有没有创建过池
public void PutObject(GameObject go, float t)
{
if (pool[go.name].Count >= MaxCount)
{
Destroy(go, t);
Debug.Log("物体大于最大个数");
}
else {
StartCoroutine(ExecutePut(go, t));
Debug.Log("进行对象池回收");
}
}
private IEnumerator ExecutePut(GameObject go, float t)
{
yield return new WaitForSeconds(t);
go.transform.SetParent(recovery);
go.SetActive(false);
pool[go.name].Enqueue(go);
}
/// <summary>
/// 物体预热/预加载
/// </summary>
/// <param name="go">需要预热的物体</param>
/// <param name="number">需要预热的数量</param>
/// TODO 既然有预热用空间换时间 应该要做一个清理用时间换空间的功能
public void Preload(GameObject go, int number)
{
if (!pool.ContainsKey(go.name))
{
pool.Add(go.name, new Queue<GameObject>());
}
for (int i = 0; i < number; i++)
{
GameObject newObject = Instantiate(go);
newObject.name = go.name;//确认名字一样,防止系统加一个(clone),或序号累加之类的
newObject.SetActive(false);
newObject.transform.SetParent(recovery);
pool[go.name].Enqueue(newObject);
}
}
}
Unity 简易对象池
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 类对象池 包含创建对象池,取对象池中的内容,回收。 对象管理类 因为使用加载AB包的时候可能会频繁创建类,但是ne...
- 本节通过一个简单的射击子弹的示例来介绍Transform的用法。子弹射击本身很容易制作,只要制作一个子弹Prefa...
- 一、 StringBuilder对象在程序中经常被用到,一般是希望在拼接字符串时获得更好的性能;但是重复构造Str...
- 一、对象池的概念 对象池背后的理念其实是非常简单的。我们将对象存储在一个池子中,当需要时在再次使用,而不是每次都实...