需要频繁大量创建和销毁对象时(比如子弹,大量敌人等)可以使用对象池,提前创建一些对象,需要的时候拿到对象并显示出来,不需要时从新隐藏存储起来。
以下是unity实现的一个子弹对象池。
//对象池 可以创建一个空的GameObject挂载此脚本
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
#region Queue实现 对象池
public GameObject bulletPrefab;
float time;
public Queue<GameObject> bulletPool = new Queue<GameObject>();//用队列来储存对象
void Start()
{
InitPool();
}
void Update()
{
time += Time.deltaTime;
if (time > 0.5f)
{
GetObjectFromPool();
time = 0;
}
if (Input.GetMouseButtonDown(0))
{
GetObjectFromPool();
}
}
//初始化池 生成10个对象 入队
void InitPool()
{
for (int i = 0; i < 10; i++)
{
GameObject go = Instantiate(bulletPrefab);
go.SetActive(false);
bulletPool.Enqueue(go);//入队
}
}
public GameObject GetObjectFromPool()
{
//队列中有可用对象 返回
if (bulletPool.Count > 0)
{
GameObject go = bulletPool.Dequeue();
go.SetActive(true);
return go;
}
//没有可用对象 需要创建新的对象
GameObject newGo = Instantiate(bulletPrefab);
return newGo;
}
//不使用的对象 入队
public void ReleaseObject(GameObject go)
{
go.SetActive(false);
go.transform.position = Vector3.zero;
bulletPool.Enqueue(go);
}
#endregion
}
//子弹脚本 挂载到子弹预制体上
using UnityEngine;
public class Bullet : MonoBehaviour
{
private GameManager gameManager;
public float speed = 1;
// Start is called before the first frame update
float time;
void Start()
{
gameManager = GameObject.FindAnyObjectByType<GameManager>();
}
// Update is called once per frame
void Update()
{
transform.Translate(new Vector3(speed * Time.deltaTime, 0, 0));
time += Time.deltaTime;
if (time > 3)
{
gameManager.ReleaseObject(this.gameObject);
time = 0;
}
}
}
以上只是基础的对象池实现,在使用中如果队列中的对象数量过大远远满足单位时间内需要显示的子弹数,要适当优化删除一些队列中的不需要元素,减少不必要的开销。