美文网首页
Unity--林老师写的高级对象池

Unity--林老师写的高级对象池

作者: ZZ曾帅 | 来源:发表于2017-10-26 09:41 被阅读0次

    由于学疏才浅,看不懂其中的奥妙,只会使用,在这里分享给大家,林老师牛逼~

    /********************************用法说明************************
     * 
     * ****************************(对象池工具)**********************
     * 
     *  **************************大吉大利,代码无bug ******************
     *          
     *  使用InitResources方法把resources文件夹下所有物体生成对象池
     * 
     *  如果不想生成全部的物体,使用InitResources<T>方法把resources文件夹下T类型物体生成对象池
     * 
     *  如果不想生成Resources文件夹上面的物体 ,使用InitObject方法把一个具体的物体生成对象池
     *      
     *  如果具体的物体很多的化,使用InitObjects方法把一堆具体的物体生成对象池        
     *                  
     *  通过GetObj名字去对象池里面拿物体,默认的物体是不会自动回收的
     *                              
     *  如果要有自动回收功能,那么可以自己实现,也可以让物体挂上继承IRecyclable的脚本,但是代码要换成GetRecycleAbleObj
     *
     *  如果对回收时间不满意,可以自己重写IRecyclable里面的init方法,把时间改长一点 
     *
     *
     *******************************************菜鸟在线    林老师
     *******************************************************2017年10月17日0:58
     ***************************************************************************/
    
    using UnityEngine;
    using System.Collections;
    using System;
    using System.Reflection;
    using System.Collections.Generic;
    
    namespace UnityEnginePool
    {
        public class ObjectPool
        {
    
            #region 单例模式
            private static ObjectPool _instance;
    
            public static ObjectPool Instance
            {
                get
                {
                    if (_instance == null)
                    {
                        _instance = new ObjectPool();
                    }
                    return _instance;
                }
            }
            #endregion
    
            #region 成员变量
    
            private object ct;
    
            private MethodInfo me;
            //所有生成对象池的库
            public List<Stack<GameObject>> mList = new List<Stack<GameObject>>();
    
            //所有生成对象池的物体的字典,用于查询是否生成过,还有查询物体的下标
            public Dictionary<string, int> mDic = new Dictionary<string, int>();
            #endregion
    
            #region 构造函数
            /// <summary>
            /// 构造函数私有化
            /// </summary>
            private ObjectPool()
            {
    
                //获取这个类
                Type ty = typeof(Creator);
                me = ty.GetMethod("Create");
                ct = Activator.CreateInstance(ty);
    
            }
            #endregion
    
            #region 泛型类型初始化到对象池
    
            /// <summary>
            /// 将Resources文件夹下所有T类型的物体实例化到对象池
            /// </summary>
            /// <param name="count">要生成的数量.</param>
            /// <typeparam name="T">写上你要实例化物体的类型.</typeparam>
            public void InitResources<T>(int count) where T : MonoBehaviour
            {
                T[] objs = Resources.LoadAll<T>("");
                for (int i = 0; i < objs.Length; i++)
                {
                    InitObject<T>(objs[i], count);
                }
            }
    
            /// <summary>
            /// 将T类型的单个物体实例化到对象池
            /// </summary>
            /// <param name="obj">要实例化的物体.</param>
            /// <param name="count">要生成的数量.</param>
            /// <typeparam name="T">写上你要实例化物体的类型.</typeparam>
            public void InitObject<T>(T obj, int count) where T : MonoBehaviour
            {
                if (mDic.ContainsKey(obj.name))
                {
                    return;
                }
                object[] o = new object[2];
                o[0] = obj.gameObject;
                o[1] = count;
                GameObject[] objs = (GameObject[])me.Invoke(ct, o);
                Stack<GameObject> stack = new Stack<GameObject>();
                for (int i = 0; i < objs.Length; i++)
                {
                    objs[i].gameObject.SetActive(false);
                    stack.Push(objs[i]);
                }
                mList.Add(stack);
                mDic.Add(obj.name, mList.Count - 1);
            }
    
            /// <summary>
            /// 将T类型的多个物体实例化到对象池
            /// </summary>
            /// <param name="obj">要实例化的物体的数组.</param>
            /// <param name="count">要生成的数量.</param>
            public void InitObjects<T>(T[] obj, int count) where T : MonoBehaviour
            {
                for (int i = 0; i < obj.Length; i++)
                {
                    InitObject<T>(obj[i], count);
                }
            }
            #endregion
    
            #region 普通类型初始化到对象池
    
            /// <summary>
            /// 将Resources文件夹下所有GameObject类型的物体实例化到对象池
            /// </summary>
            /// <param name="要生成的数量">Count.</param>
            public void InitResources(int count)
            {
                GameObject[] objs = Resources.LoadAll<GameObject>("");
                for (int i = 0; i < objs.Length; i++)
                {
                    InitObject(objs[i], count);
                }
            }
    
            /// <summary>
            /// 将GameObject类型的单个物体实例化到对象池
            /// </summary>
            /// <param name="obj">要实例化的物体.</param>
            /// <param name="count">要生成的数量.</param>
            public void InitObject(GameObject obj, int count)
            {
                if (mDic.ContainsKey(obj.name))
                {
                    return;
                }
                object[] o = new object[2];
                o[0] = obj;
                o[1] = count;
                GameObject[] objs = (GameObject[])me.Invoke(ct, o);
                Stack<GameObject> stack = new Stack<GameObject>();
                for (int i = 0; i < objs.Length; i++)
                {
                    objs[i].gameObject.SetActive(false);
                    stack.Push(objs[i]);
                }
                mList.Add(stack);
                mDic.Add(obj.name, mList.Count - 1);
            }
    
            /// <summary>
            /// 将GameObject类型的单个物体补充到不够的对象池里
            /// </summary>
            /// <param name="obj">要实例化的物体.</param>
            /// <param name="count">要生成的数量.</param>
            private void SuppleObject(Stack<GameObject> st, GameObject obj, int count)
            {
                Debug.Log("补充");
                object[] o = new object[2];
                o[0] = obj;
                o[1] = count;
                GameObject[] objs = (GameObject[])me.Invoke(ct, o);
                for (int i = 0; i < objs.Length; i++)
                {
                    objs[i].gameObject.SetActive(false);
                    st.Push(objs[i]);
                }
            }
    
            /// <summary>
            /// 将GameObject类型的多个物体实例化到对象池
            /// </summary>
            /// <param name="obj">要实例化的物体的数组.</param>
            /// <param name="count">要生成的数量.</param>
            public void InitObjects(GameObject[] obj, int count)
            {
                for (int i = 0; i < obj.Length; i++)
                {
                    InitObject(obj[i], count);
                }
            }
            #endregion
    
            /// <summary>
            /// 根据名字拿一个物体
            /// </summary>
            /// <returns>从对象池拿到的物体 .</returns>
            /// <param name="name">物体的名字.</param>
            public GameObject GetObj(string name)
            {
                if (!mDic.ContainsKey(name))
                {
                    Debug.LogError("对象池获取失败!!" + "对象池没有你要的这个物体");
                    return null;
                }
                GameObject obj = mList[mDic[name]].Pop();
                if (mList[mDic[name]].Count < 2)
                {
                    SuppleObject(mList[mDic[name]], obj, 10);
                }
                obj.gameObject.SetActive(true);
                return obj;
            }
    
    
            /// <summary>
            /// 根据名字拿一个IRecycleAble的物体
            /// </summary>
            /// <returns>从对象池拿到的物体 .</returns>
            /// <param name="name">物体的名字.</param>
            public GameObject GetRecycleAbleObj(string name)
            {
                if (!mDic.ContainsKey(name))
                {
                    Debug.LogError("对象池获取失败!!" + "对象池没有你要的这个物体");
                    return null;
                }
                GameObject obj = mList[mDic[name]].Pop();
                if (mList[mDic[name]].Count < 2)
                {
                    SuppleObject(mList[mDic[name]], obj, 10);
                }
                obj.gameObject.SetActive(true);
                
                obj.GetComponent<IRecyclable>().Init(mDic[name]);
                return obj;
            }
    
            /// <summary>
            /// 回收一个物体
            /// </summary>
            /// <param name="obj">要回收物体的GameObject.</param>
            public void CallBack(GameObject obj)
            {
                if (!mDic.ContainsKey(obj.name))
                {
                    Debug.Log("对象池回收失败!!" + obj.name + "不是从对象池出来的");
                    return;
                }
                int no = mDic[obj.name];
                mList[no].Push(obj);
                obj.gameObject.SetActive(false);
            }
    
            /// <summary>
            /// 回收一个IRecycleAble的物体
            /// </summary>
            /// <param name="obj">要回收物体的GameObject.</param>
            public void CallBackIRecycle(IRecyclable obj)
            {
                string name = obj.gameObject.name.Split('(')[0];
                if (!mDic.ContainsKey(name))
                {
                    Debug.Log("对象池回收失败!!" + name + "不是从对象池出来的");
                    return;
                }
                int no = mDic[name];
                mList[no].Push(obj.gameObject);
                obj.gameObject.SetActive(false);
            }
        }
    
        public class Creator : MonoBehaviour
        {
            public GameObject[] Create(GameObject obj, int l)
            {
                GameObject[] o = new GameObject[l];
                for (int i = 0; i < l; i++)
                {
                    o[i] = Instantiate(obj);
                }
                return o;
            }
    
    
        }
    
        public abstract class IRecyclable : MonoBehaviour
        {
    
            protected float mTime = 0.0f;
    
            protected float Duration;
    
            public float mDuration = 3.0f;
    
    
            //初始化函数
            public virtual void Init(int no)
            {
                NO = no;
                mTime = mDuration;
            }
    
    
    
            //被回收的时候调用的函数
            public virtual void OnRecycle()
            {
                ObjectPool.Instance.CallBackIRecycle(this);
            }
    
            public int NO;
    
            void Update()
            {
                if (mTime > 0.0f)
                {
                    mTime -= Time.deltaTime;
                    if (mTime < 0.0f)
                    {
                        OnRecycle();
                    }
                }
            }
        }
    
    }
    
    

    相关文章

      网友评论

          本文标题:Unity--林老师写的高级对象池

          本文链接:https://www.haomeiwen.com/subject/qtuhpxtx.html