注释
在项目上经常会遇到生成很多同样的物体,往往会对性能造成很大的影响,所以可以采用以下的对象池系统来进行简单的操作
对象池系统
这个模块的主代码,主要用于生成对象,销毁对象
public class ObjectPool : Singleton<ObjectPool>{#region 对象池/// <summary>/// 对象池/// </summary>private Dictionary<string, List<GameObject>> objectPools = new Dictionary<string, List<GameObject>>();/// <summary>/// 生成获得一个池子里的物体/// </summary>/// <param name="objectName">物体的名字</param>/// <param name="pos">位置</param>/// <param name="qua">旋转</param>/// <param name="parent">父物体</param>/// <returns>物体</returns>private GameObject SpawnObjectInternal(string objectName, Vector3 pos, Quaternion qua, Transform parent){//声明需要返回的游戏对象GameObject obj;//如果存在该子池,且子池中有对象if (objectPools.ContainsKey(objectName) && objectPools[objectName].Count > 0){//获取到对象obj = objectPools[objectName][0];//激活对象obj.SetActive(true);//从子池中移除对象objectPools[objectName].RemoveAt(0);}else{//通过名称加载对象预设体GameObject prefab = GetAssets<GameObject>(objectName);//生成对象obj = GameObject.Instantiate(prefab, pos, qua, parent);//改名obj.name = prefab.name;}//返回对象return obj;}/// <summary>/// 生成对象/// </summary>/// <param name="objectName">物体名字</param>/// <param name="pos">位置</param>/// <param name="qua">旋转</param>/// <param name="parent">父物体</param>/// <param name="initAction">事件</param>/// <returns></returns>public GameObject SpawnObject(string objectName, Vector3 pos, Quaternion qua, Transform parent, System.Action<GameObject> initAction){GameObject obj = SpawnObjectInternal(objectName, pos, qua, parent);//初始化obj.GetComponent<PoolObject>().ObjectInit(initAction);return obj;}/// <summary>/// 回收对象/// </summary>/// <param name="obj"></param>public void RecycleObject(GameObject obj){//取消激活obj.SetActive(false);//如果不存在该子池if (!objectPools.ContainsKey(obj.name)){//创造空的子池objectPools.Add(obj.name, new List<GameObject>());}//将对象放入子池objectPools[obj.name].Add(obj);//收尾obj.GetComponent<PoolObject>().ObjectDispose();}#endregion#region 资源管理/// <summary>/// 缓存资源字典/// </summary>private Dictionary<string, Object> assetsCache = new Dictionary<string, Object>();/// <summary>/// 加载资源/// </summary>/// <typeparam name="T"></typeparam>/// <param name="assetPath"></param>/// <returns></returns>public T GetAssets<T>(string assetPath) where T : Object{if (!assetsCache.ContainsKey(assetPath)){//加载资源并存入缓存池assetsCache.Add(assetPath, Resources.Load<T>(assetPath));}return assetsCache[assetPath] as T;}#endregion}
子对象父物体
在池子里的对象,主要在生成对象的时候涉及到初始化工作和收尾工作,还有自动回收,和一些必须实现的接口,主要用于继承作用
/// <summary>/// 池子里的物体/// </summary>public abstract class PoolObject : MonoBehaviour{/// <summary>/// 是否自动回收/// </summary>[Header("是否自动回收")]public bool autoRecycle;/// <summary>/// 回收时间/// </summary>[Header("回收时间")]public float recycleInterval = 2f;protected virtual void OnEnable(){if (autoRecycle){StartCoroutine(DelayRecycle());}}/// <summary>/// 自动回收/// </summary>/// <returns></returns>private IEnumerator DelayRecycle(){//延时yield return new WaitForSeconds(recycleInterval);//回收ObjectPool.Instance().RecycleObject(gameObject);}/// <summary>/// 初始化工作/// </summary>/// <param name="initAction">初始化的时候执行的事件</param>public abstract void ObjectInit(Action<GameObject> initAction);/// <summary>/// 收尾工作/// </summary>public abstract void ObjectDispose();}
子对象
主要用于继承上述代码,如下示例,子弹的脚本继承上述父物体,挂载在子弹预制体上
public class Bullet : PoolObject
{public override void ObjectInit(Action<GameObject> initAction){Debug.Log("我出来了");initAction?.Invoke(gameObject);}public override void ObjectDispose(){Debug.Log("我收尾了");}
}
实现
我们可以使用简单的测试接口进行测试,生成一个子弹
private void Update(){if (Input.GetKeyDown(KeyCode.Space)){ObjectPool.Instance().SpawnObject("Bullet", Vector3.zero, Quaternion.identity, null,(GameObject obj) => {obj.transform.position = Vector3.zero;});}}