对象池
对象池
顾名思义就是存储对象的容器。主要仅适用于需要大量对象并且使用后就销毁场景,例如射击游戏中子弹,塔防中怪物,大量生成之后就很快销毁。频繁的产生销毁对象,会消耗大量cpu资源,造成游戏卡顿,并且对象存储在堆内存
中,是不连续的空间,会造成内存碎片问题,随着运行时间的增加,程序存在闪退的现象。
对于要大量产生的对象使用一个集合存储起来,并使用一个类来维护这个集合。主要有两个方法GetObj
和Recycle
,用来提供对象和回收对象
-
在unity 中的简单实现
场景搭建- 创建一个胶囊,在创建一个空物体作为他的子物体,作为子弹的发射点
- 创建一个Sphere球体,并且保存为预制体,存放在
Resources/Prefabs
命名为bullet
- 创建一个胶囊,在创建一个空物体作为他的子物体,作为子弹的发射点
Pool.cs
using UnityEngine
public class Pool
{
//单例模式实现
static Pool _instance;
public static Pool Instance
{
get
{
if(instance == null)
{
instance = new Pool();
}
return _instance;
}
}
GameObject _obj; //需要大量产生销毁的对象
List<GameObject> pool;
private Pool()
{
pool = new List<GameObject>();
//动态获取该对象
_obj = Resources.Load<GameObject>("Prefabs/bullet");
}
public GameObject GetObj()
{
GameObject obj;
if(pool.Count ==0)
{
//pool中没有存储对象时
obj = GameObject.instantiate(_obj);
obj.SetActive(false);
obj.AddComponent<Bullet>();
pool.Add(obj);
}
obj = pool[0]; //每次只取第一个
obj.SetActive(true);
//将提供的对象从pool中移除
pool.RemoveAt(0);
return obj;
}
public void Recycle(GameObject obj)
{
//将对象失活而不是Destory。然后存入到维护的pool中
obj.SetActive(false);
pool.Add(obj);
}
}
Bullet.cs
//继承MonoBehaviour
public class Bullet:MonoBehaviour
{
void OnEnable()
{
//一定要写在OnEnable中
StartCoroutine(Recycle());
}
void Update () {
transform.Translate(Vector3.forward * 10 * Time.deltaTime);
}
//使用协程完成自动回收,也可以使用计时器
IEnumerator Recycle()
{
yield return new WaitForSeconds(1f);
BulletPool.Instance.Recycle(gameObject);
}
}
Test.cs
//挂载在胶囊上面
public class Test:MonoBehaviour
{
void Start () {
}
void Update () {
if (Input.GetKeyDown(KeyCode.Space))
{
//按空格产生子弹
GameObject bullet = BulletPool.Instance.GetObj();
bullet.transform.position = transform.GetChild(0).position;
}
}
}