Unity游戏对象池和单例模式的配合使用

       本次介绍两个脚本GameObjectPool游戏对象池类和MonoSingLeton单例模式类。

       在Unity中不论是在游戏中或者是别的应用场景,我们有时候会需要重复产生相同的物体并销毁掉,例如子弹就得不断生成不断销毁。但这样是很消耗性能的。所以有的大佬就设计了游戏对象池这个概念。

       游戏对象池脚本挂在一个空物体上,玩家在Unity中不需要使用 Instantiate() 方法进行创建物体。而是用我GameObjectPool脚本中的CreateObject(string key,GameObject go,Vector3 pos,Quaternion rat)进行创建。依次是预制件名称、预制件对象、三维坐标数据、旋转数据。当使用这个方法创建时物体时,该物体会成为对象池的子物体,而当需要到销毁时对象池会将该物体隐藏,若再次需要用到,则重新设置物体的坐标和旋转并启用。若对象池内的物体不够用了才会重新生成一个对象。

       游戏对象池在游戏中只能有一个,所以需要将他设计为单例模式。只需要让游戏对象池继承他便可。然后调用他的instance方法就可以了。

————————————————————————————————————————

MonoSingLeton脚本

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

///

/// 单例模式挂载脚本

///

public abstract class MonoSingLeton : MonoBehaviour where T : MonoSingLeton

{

    private static T m_Instance = null;

    //3.

    //设计阶段,写脚本没有挂在物体上,希望脚本单例模式

    //运行时,需要这个脚本唯一实例,第1次,调用instance

    public static T instance

    {

        get

        {

            if(m_Instance == null)

            {

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

                if (m_Instance == null)

                {

                    m_Instance = new GameObject("Singleton of" + typeof(T).ToString(), typeof(T)).GetComponent();

                    m_Instance.Init();

                }

            }


            return m_Instance;

        }

    }

    private void Awake()

    {

        if (m_Instance == null)

        {

            m_Instance = this as T;

        }

    }

    //提供初始化一种选择

    public virtual void Init() { }

    //当程序退出时做清理工作,单例模式对象=null

    private void OnApplicationQuit()

    {

        m_Instance = null;

    }

}

——————————————————————————————————————

游戏对象池脚本

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

///

/// 游戏对象池

///

public class GameObjectPool : MonoSingLeton

{

    //1.创建池

    private GameObjectPool()

    {

    }

    //static private GameObjectPool obj = new GameObjectPool();

    ////提供得到对象的唯一通道

    //static public GameObjectPool GetObject()

    //{

    //    return obj;

    //}

    private Dictionary> cache = new Dictionary>();

    //2.创建一个对象并使用对象

    public GameObject CreateObject(string key,GameObject go,Vector3 pos,Quaternion rat)

    {

        //1.查找池中有无可用的游戏对象

        GameObject tempGo = FindUsable(key);

        //2.池中有从池中返回

        if (tempGo != null)

        {

            tempGo.transform.position = pos;

            tempGo.transform.rotation = rat;

            tempGo.SetActive(true);  //表示当前正在使用

        }

        else//3.池中没有加载,放入池中再返回

        {

            tempGo = Instantiate(go, pos, rat) as GameObject;

            //放入池中

            Add(key, tempGo);

        }

        tempGo.transform.parent = transform;

        return tempGo;

    }

    private GameObject FindUsable(string key)

    {

        if (cache.ContainsKey(key))

        {

            //从列表中找出未激活的游戏物体

            return cache[key].Find((p) => !p.activeSelf);

        }

        return null;

    }

    private void Add(string key,GameObject go)

    {

        //检查池中有没有需要的key,没有的话则创建对应列表

        if (!cache.ContainsKey(key))

        {

            cache.Add(key,new List());

        }

        cache[key].Add(go);

    }

    //3.  释放资源:从池中删除对象

    //3.1 释放部分:按key释放

    public void Clear(string key)

    {

        if (cache.ContainsKey(key))

        {

            //销毁场景中游戏物体

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

            {

                Destroy(cache[key][i]);

            }

            //紧紧移除了字典中对象地址

            cache.Remove(key);

        }

    }

    //3.2 释放全部

    public void ClearAll()

    {

        List list = new List(cache.Keys);

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

        {

            Clear(list[i]);

        }

    }

    //4.  回收对象【从画面中消失】

    //4.1 即使回收对象

    public void CollectObject(GameObject go)

    {

        go.SetActive(false);

    }

    //4.2 延时回收对象  协程

    public void CollectObject(GameObject go,float delay)

    {

        StartCoroutine(CollectDelay(go,delay));

    }

    private IEnumerator CollectDelay(GameObject go,float delay)

    {

        yield return new WaitForSeconds(delay);

        CollectObject(go);

    }

}

你可能感兴趣的:(Unity游戏对象池和单例模式的配合使用)