using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public class ObjectPool<T> { private readonly Stack<T> stack = new Stack<T>(); private readonly Func<T> actionOnNew; private readonly UnityAction<T> actionOnGet; private readonly UnityAction<T> actionOnRelease; public int CountAll { get; private set; } public int CountInactive { get { return stack.Count; } } public int CountActive { get { return CountAll - CountInactive; } } public ObjectPool(Func<T> onNew, UnityAction<T> onGet = null, UnityAction<T> onRelease = null) { actionOnNew = onNew; actionOnGet = onGet; actionOnRelease = onRelease; } public T Get() { T element; if (stack.Count == 0) { element = actionOnNew == null ? default(T) : actionOnNew.Invoke(); CountAll++; } else { element = stack.Pop(); } if (actionOnGet != null) { actionOnGet.Invoke(element); } return element; } public void Release(T element) { if (stack.Count > 0 && ReferenceEquals(stack.Peek(), element)) { Debug.LogError("Internal error. Trying to destroy object that is already released to pool."); } if (actionOnRelease != null) { actionOnRelease.Invoke(element); } stack.Push(element); if (stack.Count > CountAll) { CountAll = stack.Count; } } }
使用泛型和委托简化代码,扩展性强。
使用示例:
Bullet类:
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bullet : MonoBehaviour { private int speed; private int damage; private float lifeTime = 10.0f; private float lifeTimer = 0; public delegate void BulletDestroyEvent(Bullet bullet); public event BulletDestroyEvent OnBulletDestroy; public int Speed { get { return speed; } set { speed = value; } } public int Damage { get { return damage; } set { damage = value; } } public float LifeTime { get { return lifeTime; } set { lifeTime = value; } } void Start () { } void Update () { if(Input.GetKeyDown(KeyCode.Mouse1)) { OnBulletDestroy.Invoke(this); } lifeTimer += Time.deltaTime; if(lifeTimer >= LifeTime) { lifeTimer = 0.0f; OnBulletDestroy.Invoke(this); } } void OnCollisionEnter(Collision collision) { OnBulletDestroy.Invoke(this); } }
ObjectPoolManager:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ObjectPoolManager : MonoBehaviour { public GameObject bulletPrefab; public ObjectPool<Bullet> bulletPool; public List<Bullet> bulletList; void Start () { bulletPool = new ObjectPool<Bullet>(BulletPoolOnNew,BulletOnGet,BulletOnRelease); } void Update () { if(Input.GetKeyDown(KeyCode.Mouse0)) { //generate one bullet bulletList.Add(bulletPool.Get()); } if(Input.GetKeyDown(KeyCode.W)) { //delete one bullet bulletPool.Release(bulletList[0]); } } //pool method Bullet BulletPoolOnNew() { var bulletObject = Instantiate(bulletPrefab) as GameObject; bulletObject.GetComponent<Bullet>().OnBulletDestroy += bulletPool.Release; return bulletObject.GetComponent<Bullet>(); } void BulletOnGet(Bullet bullet) { bullet.gameObject.SetActive(true); } void BulletOnRelease(Bullet bullet) { bullet.gameObject.SetActive(false); } }