Unity中的万能对象池
在Unity开发中,对象池是一个非常常用的技术,在需要频繁创建和销毁游戏对象的场景下,使用对象池能够提高游戏运行的效率和性能。
不过,与常规的对象池不同的是,本文介绍的是一种使用泛型和接口实现的万能对象池,不仅可以复用GameObject对象,同时也能够重复使用所有继承自MonoBehaviour的组件。
实现方式
首先,定义一个接口IPoolable
,它包含了两个方法,OnSpawn
和OnDespawn
,分别代表对象被获取和归还时的操作:
public interface IPoolable
{
void OnSpawn();
void OnDespawn();
}
接着,定义一个泛型类ObjectPool<T>
,它继承自MonoBehaviour
,因为我们需要使用协程来实现对象的自动归还。ObjectPool<T>
有以下属性和方法:
public class ObjectPool<T> : MonoBehaviour where T : Component, IPoolable
{
[SerializeField]
private T prefab;
private Queue<T> objectQueue = new Queue<T>();
public T Get()
{
if (objectQueue.Count == 0)
{
return Instantiate(prefab);
}
else
{
T objectToGet = objectQueue.Dequeue();
objectToGet.gameObject.SetActive(true);
objectToGet.OnSpawn();
return objectToGet;
}
}
public void Return(T objectToReturn)
{
objectToReturn.OnDespawn();
objectToReturn.gameObject.SetActive(false);
objectQueue.Enqueue(objectToReturn);
}
}
其中,prefab
属性为对象池内保存的对象预制体。objectQueue
是一个FIFO的队列,用来存储已经使用过的对象。Get()
方法会从队列中获取一个对象,如果队列为空就新建一个对象。获取到的对象需要被激活,并调用它的OnSpawn()
方法。Return(objectToReturn)
方法则是将对象归还至队列,调用它的OnDespawn()
方法,并设置它的游戏对象为不激活状态。
最后,我们让需要使用对象池的GameObject继承自IPoolable
接口,并手动实现OnSpawn
和OnDespawn
方法。这样,我们就可以把任意继承自MonoBehaviour
的组件加入到我们的对象池中,用法非常灵活。
使用示例
假设我们想要使用这个万能对象池来实现子弹的复用,现在我们需要在场景中创建一个子弹预制体,预制体上需要挂载Bullet
脚本:
public class Bullet : MonoBehaviour, IPoolable
{
public float speed = 10.0f;
public float lifetime = 5.0f;
private Coroutine lifetimeCoroutine;
public void OnSpawn()
{
lifetimeCoroutine = StartCoroutine(LifetimeTimer());
}
public void OnDespawn()
{
StopCoroutine(lifetimeCoroutine);
}
private IEnumerator LifetimeTimer()
{
yield return new WaitForSeconds(lifetime);
ObjectPool<Bullet>.Instance.Return(this);
}
void Update()
{
transform.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
Bullet
脚本实现了IPoolable
接口,并在OnSpawn
方法中启动了一个携程,用来计算子弹的寿命。当寿命结束时,我们需要将子弹归还到对象池中。
在我们的游戏场景中创建一个空对象,将ObjectPool
脚本挂载上去:
public class ObjectPool : MonoBehaviour
{
public static ObjectPool Instance;
void Awake()
{
Instance = this;
}
}
在需要使用子弹的脚本中,我们只需要调用ObjectPool<Bullet>.Instance.Get()
方法获取一个子弹,而不是手动使用Instantiate
来创建它:
ObjectPool<Bullet>.Instance.Get();
当需要归还对象时,调用Return()
方法:
ObjectPool<Bullet>.Instance.Return(bullet);
总结
这篇文章介绍了一种使用泛型和接口实现的万能对象池,可以方便灵活地复用GameObject和所有继承自MonoBehaviour的组件。这种实现方式避免了重复编写对象池代码的麻烦,大大提高开发效率。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:unity中的万能对象池 - Python技术站