对象池的使用 实现

MonoSingleton 

—— 单例基类

任何继承自 MonoSingleton 泛型基类的脚本/类 都是单例类

using UnityEngine;

/// <summary>/// 泛型单例基类 —— 任何继承自该类的类,都是单例类/// </summary>/// <typeparam name="T">泛型</typeparam>

public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>

{

    private static T instance;

    public static T Instance

    {

        get        {

            if (instance == null)

            {

                instance = FindObjectOfType(typeof(T)) as T;

                if (instance == null) instance = new GameObject("Chinar Single of " + typeof(T).ToString(), typeof(T)).GetComponent<T>();

            }

            return instance;

        }

    }

    private void Awake()    {

        if (instance == null) instance = this as T;

    }

    private void OnApplicationQuit()    {

        instance = null;

    }

}


2

ObjectPool —— 对象池

新建一个脚本 ObjectPool 继承自泛型基类 MonoSingleton《ObjectPool》

是以 ObjectPool 就会是一个单例类

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

/// <summary>/// 对象池(重复调用/使用的游戏物体) 子弹,技能,导弹,敌人/// </summary>

public class ObjectPool : MonoSingleton<ObjectPool>

{

    //字段  池 技能预设物(因为一个技能可能有多个预制件) 技能的复用性 

   private   Dictionary> cache = new Dictionary<string, List<GameObject>();

    int        i    = 0; //标记 0  

  /// <summary>    /// 创建显示对象    /// </summary>   

 /// <returns>The object.</returns>    

/// <param name="key">对象名称</param>  

  /// <param name="go">对象的预制件</param> 

   /// <param name="position">对象的新位置</param>   

 /// <param name="quaternion">对象的角度</param>   

 public GameObject CreateObject(string key, GameObject go, Vector3 position, Quaternion quaternion)    {

        GameObject tempgo = cache.ContainsKey(key) ? cache[key].Find(p => !p.activeSelf) : null; //返回池中未激活的对象,所有都被激活就返回空,赋值给临时对象       

 if (tempgo != null)                                                                      //如果临时对象不为空      

  {

            tempgo.transform.position = position;  //设置位置   

         tempgo.transform.rotation = quaternion; //旋转信息 

       }

        else //否则,就是空了。(也就是没能从池子里取出对象)   

     {

            tempgo = Instantiate(go, position, quaternion); //那就根据传入的预设物,生成一个新物体       

     print("实例化物体数量:" + i++);

            if (!cache.ContainsKey(key)) //池中没有键          

              {

                cache.Add(key, new List<GameObject>()); //新建一个 列表  

                  }

            cache[key].Add(tempgo); //给字典中的列表加入/add 临时物体,如果有键就直接添加了  

      }

        tempgo.SetActive(true); //并启用临时物体       

 return tempgo;          //返回  

  }

    /// <summary>    /// 直接回收    /// </summary>  

  /// <param name="go">Go.</param>  

  public void CollectObject(GameObject go)   

 {

        go.SetActive(false);

    }

    /// <summary>    /// 延迟回收    /// </summary>   

 /// <param name="go">Go.</param>  

  /// <param name="delay">Delay.</param>  

  public void CollectObject(GameObject go, float delay)    {

        StartCoroutine(Collect(go, delay));

    }

    private IEnumerator Collect(GameObject go, float delay)  

  {

        yield return newWaitForSeconds(delay);

        CollectObject(go);

    }

    /// <summary>    /// 释放资源    /// </summary>   

 /// <returns>The clear.</returns>   

 /// <param name="key">Key.</param>  

  public void Clear(string key)    {

        if (cache.ContainsKey(key))

        {

                    //Destroy当中所有的对象     

                   for (int i = 0; i < cache[key].Count; i++)

                    {

                        Destroy(cache[key][i]);

                       }

            //清除键当中的所有值     

               //cache[key].Clear();          

              //清除这个键(键值一起清除)    

                cache.Remove(key);

        }

    }

    /// <summary>    /// 释放所有对象池    /// </summary>  

  public void ClearAll()    {

        var list = new List<string>(cache.Keys);

        for (int i = 0; i < list.Count; i++)

        {

            Clear(list[i]);

        }

    }

}


3

PoolTest —— 测试对象池的使用

新建一个脚本 PoolTest 用来测试对象池的使用

using UnityEngine;

/// <summary>

/// 测试对象池的调用

/// </summary>

public class PoolTest : MonoBehaviour{

    GameObject go;  //临时对象   

 GameObject item; //临时对象池对象 

   voidStart()    {

        go = Resources.Load<GameObject>("Cube"); //在Resources文件目录下做一个Cube预设物  

                          }

    voidUpdate()    {

        if (Input.GetKey(KeyCode.Space)) //按下空格创建一个Cube 

       {

            item                    =  ObjectPool.Instance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));

            item.transform.position += new Vector3(0, 0, 1);

        }

        if (Input.GetMouseButtonDown(0)) //按下左键执行回收对象     

          {

                        if (item != null)

                        {

                            ObjectPool.Instance.CollectObject(item, 0.2f);

                            }

        }

        if (Input.GetMouseButtonDown(1)) //按下右键执行清除已经生成的对象   

     {

            ObjectPool.Instance.Clear("Object1");

        }

    }

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容