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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leonardo_Davinci/article/details/78646562

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


创建对象池的步骤:

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 initialization
	void Start () {
        //在Resources文件下加载Cube预制键
        go = Resources.Load("Cube") as GameObject;
	}
	
	// Update is called once per frame
	void 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");
        }
	}
}



猜你喜欢

转载自blog.csdn.net/leonardo_Davinci/article/details/78646562
今日推荐