美文网首页
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--林老师写的高级对象池

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

  • Unity--简单的对象池

    简单的对象池分三步走: 建立对象池 拿到对象 回收对象 Test为对象池,Obj为自动回收的物体 Test.cs ...

  • C# 链表

    链表介绍 Unity 用C#写的链表类 简述链表和数组的区别 Unity--链表实现贪吃蛇

  • Unity高级 -- 对象池(Object Pool)

    我们在做项目的时候,如果同一个物体要用到好多次,我们就不要再用实例化了,因为每次创建一个新物体是很消耗资源的,所以...

  • Laya_2D示例项目使用对象池预制体的创建、位置设置和添加到父

    //使用对象池创建盒子 1.对象池的使用 对象池创建箱子 let box = Laya.Pool.getI...

  • Unity 类对象池资源池对象池

    类对象池 包含创建对象池,取对象池中的内容,回收。 对象管理类 因为使用加载AB包的时候可能会频繁创建类,但是ne...

  • Swift的对象池模式及如何处理并发访问

    对象池模式用来管理一组可重用的对象,可从对象池获取对象来完成任务,用完之后再还给对象池。系统UITableView...

  • Netty对象池实现分析

    什么是对象池技术?对象池应用在哪些地方? 对象池其实就是缓存一些对象从而避免大量创建同一个类型的对象,类似线程池的...

  • wait() notify() notifyAll()讲解

    1.锁池 等待池 每个对象都内置了锁池跟等待池。锁池: 某个线程拥有了该对象的锁,其他线程执行时,遇到该对象修饰的...

  • 对象池

    一、对象池概述: 对于那些实例化开销比较大,并且生命周期比较短的对象,我们可以通过池就行管理。所谓池,就相当于一个...

网友评论

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

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