Unity对象池
对象池,每次都会调用第一个没有被隐藏的对象。
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool<T> where T : Component
{
private Queue<T> objectQueue;//没有被使用的对象的队列
private HashSet<T> activeObjects;//已经激活对象的队列
private T prefab;//对象的预制体
private int poolSize;//对象池的大小
private int initialPoolSize;//对象池初始大小
//创建对象池,对象的预制体,对象池的初始大小
public ObjectPool(T prefab, int poolSize)
{
this.prefab = prefab;
this.poolSize = poolSize;
this.initialPoolSize = poolSize;
objectQueue = new Queue<T>();
activeObjects = new HashSet<T>();
for (int i = 0; i < poolSize; i++)
{
T obj = GameObject.Instantiate(prefab);
obj.gameObject.SetActive(false);
objectQueue.Enqueue(obj);
}
}
//获取对象池中的物体,默认是会获取第一个物体,
public T GetObject()
{
if (objectQueue.Count == 0)
{
ExpandPool();
}
T obj = objectQueue.Dequeue();
obj.gameObject.SetActive(true);
activeObjects.Add(obj);
return obj;
}
//拓展池,当池内的物体不够用的时候会自行拓展
private void ExpandPool()
{
int newSize = poolSize * 2;
for (int i = poolSize; i < newSize; i++)
{
T obj = GameObject.Instantiate(prefab);
obj.gameObject.SetActive(false);
objectQueue.Enqueue(obj);
}
poolSize = newSize;
Debug.Log($"Pool expanded to size: {poolSize}");
}
//使用完毕后将对象返回到对象池中去
public void ReturnObject(T obj)
{
obj.gameObject.SetActive(false);
objectQueue.Enqueue(obj);
activeObjects.Remove(obj);
}
/// <summary>
/// 获取池中的全部active对象
/// </summary>
/// <returns></returns>
public List<T> GetActiveObjects()
{
return new List<T>(activeObjects);
}
}
用法:
using UnityEngine;
public class Bullet : MonoBehaviour
{
// Bullet 类的具体实现
publick BulletSpawner bullpool;
private void Start(){
Invoke(nameof(SS),1.0f);
}
private void SS(){
bullpool. ReturnBullet(this);
}
}
public class BulletSpawner : MonoBehaviour
{
public Bullet bulletPrefab;
private ObjectPool<Bullet> bulletPool;
void Start()
{
//设置对象池的大小
bulletPool = new ObjectPool<Bullet>(bulletPrefab, 10);
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Bullet bullet = bulletPool.GetObject();
bullet.transform.position = transform.position;
// 其他初始化逻辑
}
}
public void ReturnBullet(Bullet bullet)
{
bulletPool.ReturnObject(bullet);
}
}