Unity 对象池的简单介绍(Dictionary使用)

来源:互联网 发布:全球大数据 2017 编辑:程序博客网 时间:2024/05/29 07:00

使用对象池的目的:增加频繁使用的游戏物体的   复用性  (游戏物体(敌人小兵)反复的创建与销毁  会消耗比较多的性能)


创建对象池的步骤:

1.创建一个存放对象的字典(对象池)

2.对对象池的操作方法

2.1创建对象                     CreateObject()

2.2为对象池添加元素       Add()

2.3寻找可以使用的对象   FindUseObj()

2.4回收对象                     CollectObject()

3.释放资源                       Clear();


实现如下

1.实现一个单例,用于管理代码

using System.Collections;using System.Collections.Generic;using UnityEngine;public class MonoSingleton<T>:MonoBehaviour where T:Component{    private static T t;    public static T Intance{        get{            t = GameObject.FindObjectOfType(typeof(T)) as T;            if(t==null)            {                GameObject go = new GameObject();                t = go.AddComponent<T>();                go.name = t + "Object";            }            //在场景切换时不要销毁            DontDestroyOnLoad(t);            return t;        }    }}
2.实现对象池

using System.Collections;using System.Collections.Generic;using UnityEngine;/// <summary>/// 对象(频发使用的游戏物体)  子弹  技能 敌人/// </summary>public class ObjectPool : MonoSingleton<ObjectPool> {    //1.字段  池   例如:横扫千军   技能预制件(因为一个技能可能有多个预制件) 技能的复用性    private Dictionary<string, List<GameObject>> cache =        new Dictionary<string, List<GameObject>>();    int i = 0;    //2.方法    //2.1 创建    //工具类   加载资源   字典  名称  资源    /// <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 = FindUseObj(key);        if(tempgo!=null)        {            tempgo.transform.position = position;            tempgo.transform.rotation = quaternion;        }        else{            tempgo = Instantiate(go, position, quaternion) as GameObject;            print(i++);            Add(key,tempgo);        }        tempgo.SetActive(true);        return tempgo;    }/// <summary>    /// 为对象池添加元素    /// </summary>    /// <returns>The add.</returns>    /// <param name="key">Key.</param>    /// <param name="tempGo">Temp go.</param>    public void Add(string key, GameObject tempGo)    {        //对象池当中如果没有键(添加键)        if(!cache.ContainsKey(key))        {            cache.Add(key,new List<GameObject>());        }        //找到相应的值,为这个列表中添加tempGo        //List中的Add方法        //对象池中有键就直接在其list中添加值        cache[key].Add(tempGo);    }    /// <summary>    /// 寻找可以使用的对象    /// </summary>    /// <returns>The use object.</returns>    /// <param name="key">键</param>    public GameObject FindUseObj(string key)    {        //在池中且未被使用的对象        if(cache.ContainsKey(key))        {            //返回找到的第一个可用的对象(没有返回 null)            return cache[key].Find(p=>!p.activeSelf);            /*上面(泛型委托Lambda)这句话的意思             *p=cache[key][i]             *if(!cache[key][i].activeSelf=!p.activeSelf)             *             *实现的方法如下             * for(int i;i<cache[key].Count;i++)             * {             * if(!cache[key][i].activeSelf)             *     return cache[key][i];             * }            */        }        return null;    }    /// <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 new WaitForSeconds(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.简单使用对象池

using System.Collections;using System.Collections.Generic;using UnityEngine;public class PoolTest : MonoBehaviour {    GameObject go;    GameObject item;// Use this for initializationvoid Start () {        //在Resources文件下加载Cube预制键        go = Resources.Load("Cube") as GameObject;}// Update is called once per framevoid Update () {        //按下空格创建一个Cube        if(Input.GetKeyDown(KeyCode.Space))        {            item = ObjectPool.Intance.CreateObject("Object1", go, Vector3.zero, new Quaternion(0, 0, 0, 0));        }        //按下左键执行回收        if(Input.GetMouseButtonDown(0))        {            if (item != null)            {                ObjectPool.Intance.CollectObject(item, 2);            }        }        //按下右键执行清除        if(Input.GetMouseButtonDown(1))        {            ObjectPool.Intance.Clear("Object1");        }}}