Common(十四)—— ObjectPool对象池

目录为:Assets/Scripts/Common/
文件为ObjectPool.cs
这个文件主要定义了一个对象池,可以参考一下.
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Linq;

//缓存物体类型
public enum PoolObjectType
{
    POT_Effect,     //Effect
    POT_MiniMap,    //MiniMap
    POT_Entity,     //Entity
    POT_UITip,      //UITip
    POT_XueTiao,    //血条
    //POT_Type2
}

//缓存池内GameObject的Info
public class PoolGameObjectInfo
{
    public string name;

    //缓存时间
    public float mCacheTime = 0.0f;

    //缓存物体类型
    public PoolObjectType type;

    //如果是特效,特效的显示等级
    public EffectLodLevel lodLevel;

    #region //拖尾处理

    //可以重用
    public bool mCanUse = true;

    //重置时间
    public float mResetTime = .0f;

    //拖尾原始时间
    public Dictionary<TrailRenderer, float> mTrailTimes = new Dictionary<TrailRenderer, float>();

    #endregion
}

//GameObject缓存池
public class PoolInfo
{
    //缓存队列
    public Dictionary<GameObject, PoolGameObjectInfo> mQueue = new Dictionary<GameObject, PoolGameObjectInfo> ();
}

//总的缓存池单例
public class GameObjectPool: Singleton<GameObjectPool>
{
    //缓存GameObject Map
    private Dictionary<String, PoolInfo> mPoolDic = new Dictionary<string, PoolInfo> ();
    //缓存GameOb节点
    private GameObject objectsPool;

    //一般的对象所能在缓存池内待的时间,超过了就销毁
    private float mCacheTime = 1800.0f;

    //删除队列
    private List<GameObject> mDestroyPoolGameObjects = new List<GameObject> ();

    //取得可用对象
    private bool TryGetObject(PoolInfo poolInfo, out KeyValuePair<GameObject, PoolGameObjectInfo> objPair)
    {
        //个数大于0
        if (poolInfo.mQueue.Count > 0)
        {
            //遍历poolInfo的mQueue
            foreach (KeyValuePair<GameObject, PoolGameObjectInfo> pair in poolInfo.mQueue)
            {
                GameObject go = pair.Key;
                PoolGameObjectInfo info = pair.Value;

                //是否可重用
                if (info.mCanUse)
                {
                    objPair = pair;
                    //取第一个可用的,然后返回true
                    return true;
                }
            }
        }

        objPair = new KeyValuePair<GameObject, PoolGameObjectInfo> ();
        //没有可用的,返回false
    }

    //获取缓存物体
    public GameObject GetGO(String res)
    {
        //有效性检查
        if (null == res)
        {
            return null;
        }

        //查找对应pool,如果没有缓存
        KeyValuePair<GameObject, PoolGameObjectInfo> pair;

        //res对应的poolInfo不存的 || poolInfo对应的pair不存在,,,就从prefab加载一个再返回
        if (!mPoolDic.TryGetValue(res, out PoolInfo) || !TryGetObject(PoolInfo, out pair))
        {
            //新创建
            //Debug.LogError("res = " + res);
            //ResourceUnit这边放到后面再看
            ResourceUnit unit = ResourcesManager.Instance.loadImmediate (res, ResourceType.PREFAB);
            if (unit.Asset == null)
            {
                Debug.Log ("can not find the resource" + res);
            }

            return GameObject.Instantiate (unit.Asset) as GameObject;
        }

        //出队列数据
        GameObject go = pair.Key;
        PoolGameObjectInfo info = pair.Value;

        //从缓存池里删掉
        PoolInfo.mQueue.Remove (go);

        //使有效
        EnablePoolGameObject(go, info);

        //返回缓存GameObject
        return go;
    }

    //用完了以后就放回pool里面
    //销毁并不在这里进行
    //这里还用来在ReadPreLoadConfig那部分把预加载的effect放进pool
    public void ReleaseGO(String res, GameObject go, PoolObjectType type)
    {
        //获取缓存节点,设置为不可见位置
        if (objectsPool == null)
        {
            objectsPool = new GameObject ("ObjectPool");
            //UIPanel:NGUI里面的
            objectsPool.AddComponent<UIPanel> ();
            objectsPool.transform.localPosition = new Vector3 (0, -5000, 0);
        }

        if (null == res || null == go)
        {
            //Debug.LogError(res + "Release go error");
            return;
        }

        //拖尾处理
        if (go.tag == "nopool")
        {
            GameObject.Destroy (go);
            return;
        }

        PoolInfo poolInfo = null;
        //没有就创建
        if (!mPoolDic.TryGetValue(res, out poolInfo))
        {
            poolInfo = new PoolInfo ();
            mPoolDic.Add (res, poolInfo);
        }

        PoolGameObjectInfo poolGameObjInfo = new PoolGameObjectInfo ();
        poolGameObjInfo.type = type;
        poolGameObjInfo.name = res;

        //无效缓存物体
        DisablePoolGameObject (go, poolGameObjInfo);

        //保存缓存GameObject,会传入相同的go,有隐患
        //poolInfo.mQueue.Add(go, poolGameObjInfo);
        poolInfo.mQueue [go] = poolGameObjInfo;
    }

    //设置缓存物体有效
    //总的来说就是把go设置为active
    //enable以后就取出去用
    public void EnablePoolGameObject(GameObject go, PoolGameObjectInfo info)
    {
        //特效Enable
        if (info.type == PoolObjectType.POT_Effect)
        {
            go.SetActive (true);

            //prewarm的情况需要模拟一个周期运行
            if (go.tag == "prewarm")
            {
                go.transform.localPosition = new Vector3 (0, -5000, 0);

                ParticleSystem[] particles = go.GetComponentsInChildren<ParticleSystem> (true);
                foreach (ParticleSystem part in particles)
                {
                    if (part.gameObject.tag == "prewarm" && part.loop)
                    {
                        part.Simulate (part.duration);
                        part.Play ();
                    }
                }

                go.transform.localPosition = new Vector3 (0, 0, 0);
            }

            //拖尾处理
            if (go.tag == "trail")
            {
                ParticleSystem[] particles = go.GetComponentsInChildren<ParticleSystem> (true);
                foreach (ParticleSystem part in particles)
                {
                    part.gameObject.SetActive (true);
                }

                XffectComponent[] xffects = go.GetComponentsInChildren<XffectComponent> (true);
                foreach(XffectComponent xffect in xffects)
                {
                    xffect.Active ();
                }

                TrailRenderer[] trailRenders = go.GetComponentsInChildren<TrailRenderer> (true);
                //拖尾时间
                foreach(TrailRenderer trail in trailRenders)
                {
                    if (info.mTrailTimes.ContainsKey(trail))
                    {
                        trail.time = info.mTrailTimes [trail];
                    }
                }

                MeshRenderer[] renders = go.GetComponentsInChildren<MeshRenderer> (true);
                foreach(MeshRenderer render in renders)
                {
                    render.gameObject.SetActive (true);
                }
            }

            go.transform.parent = null;
        }
        else if (info.type == PoolObjectType.POT_MiniMap)
        {
            go.SetActive (true);
            go.transform.parent = null;
        }
        else if (info.type == PoolObjectType.POT_Entity)
        {
            go.SetActive (true);
            go.transform.parent = null;
        }
        else if (info.type == PoolObjectType.POT_UITip)
        {
            go.SetActive (true);
            go.transform.parent = null;
        }
        else if (info.type == PoolObjectType.POT_XueTiao)
        {
            //do nothing
        }

        info.mCacheTime = 0.0f;
    }

    //设置缓存物体无效
    public void DisablePoolGameObject(GameObject go, PoolGameObjectInfo info)
    {
        //特效Disable
        if (info.type == PoolObjectType.POT_Effect) 
        {
            ParticleSystem[] particles = go.GetComponentsInChildren<ParticleSystem> (true);
            foreach (ParticleSystem part in particles)
            {
                //清除所有粒子
                part.Clear ();
            }

            //解绑到poolGameObject节点
            go.transform.parent = objectsPool.transform;

            //拖尾处理
            if (go.tag == "trail") 
            {
                info.mCanUse = false;

                TrailRenderer[] trailRenders = go.GetComponentsInChildren<TrailRenderer> ();
                foreach (TrailRenderer trail in trailRenders)
                {
                    info.mTrailTimes [trail] = trail.time;
                    trail.time = -10;
                }

                XffectComponent[] xffects = go.GetComponentsInChildren<XffectComponent> (true);
                foreach (XffectComponent xffect in xffects)
                {
                    xffect.DoFinish ();
                    xffect.gameObject.SetActive (false);
                }

                MeshRenderer[] renders = go.GetComponentsInChildren<MeshRenderer> (true);
                foreach (MeshRenderer render in renders) 
                {
                    render.gameObject.SetActive (false);
                }

                foreach (ParticleSystem part in particles) 
                {
                    part.gameObject.SetActive (false);
                }
            } 
            else 
            {
                info.mCanUse = true;
                go.SetActive (false);
            }
        } 
        else if (info.type == PoolObjectType.POT_MiniMap) 
        {
            //go.transform.parent = objectsPool.transform;
            go.SetActive (false);
        } 
        else if (info.type == PoolObjectType.POT_Entity) 
        {
            //解绑到poolGameObject节点
            go.transform.parent = objectsPool.transform;
            go.SetActive (false);
        } 
        else if (info.type == PoolObjectType.POT_UITip)
        {
            //解绑到poolGameObject节点
            go.transform.parent == objectsPool.transform;
            go.SetActive (false);
        }
        else if (info.type == PoolObjectType.POT_XueTiao)
        {
            go.transform.parent = objectsPool.transform;
            XueTiaoUI xt = go.GetComponent<XueTiaoUI> ();
            xt.SetVisible (false);
        }
    }

    //清除
    public void Clear()
    {
        mPoolDic.Clear ();
        mDestroyPoolGameObjects.Clear ();
        objectsPool = null;
    }

    float mTotalTime = 0;

    public void OnUpdate()
    {
        //每隔0.1更新一次
        mTotalTime += Time.deltaTime;
        if (mTotalTime <= 0.1f)
        {
            return;
        }
        else
        {
            mTotalTime = 0;
        }

        float deltaTime = Time.deltaTime;

        //遍历数据
        foreach(PoolInfo poolInfo in mPoolDic.Values)
        {
            //死亡列表
            mDestroyPoolGameObjects.Clear ();

            foreach (KeyValuePair<GameObject, PoolGameObjectInfo> pair in poolInfo.mQueue)
            {
                GameObject obj = pair.Key;
                PoolGameObjectInfo info = pair.Value;

                info.mCacheTime += deltaTime;

                //mCacheTime默认1800s
                float mAllCacheTime = mCacheTime;

                //POT_UITip缓存3600s
                if (info.type == PoolObjectType.POT_UITip)
                {
                    mAllCacheTime = 3600.0f;
                }

                //缓存时间到
                //加入DestroyPool
                if (info.mCacheTime >= mAllCacheTime)
                {
                    mDestroyPoolGameObjects.Add (obj);
                }

                //拖尾重置计时
                //如果mCanUs为false,那就等待1s再设置为true,然后就等待下次再使用或销毁
                if (!info.mCanUse)
                {
                    info.mResetTime += deltaTime;

                    if (info.mResetTime > 1.0f)
                    {
                        info.mResetTime = 0.0f;
                        info.mCanUse = true;

                        obj.SetActive (false);
                    }
                }
            }

            //移除掉
            //这里说明:缓存池里的物体并不会一直存在,超过mCacheTime没用过的话就销毁,不再占用资源,要用的时候会再重新创建
            for (int k = 0; k < mDestroyPoolGameObjects.Count; k++)
            {
                GameObject obj = mDestroyPoolGameObjects [k];
                //obj.transform.parent = null;
                GameObject.DestroyImmediate (obj);

                poolInfo.mQueue.Remove (obj);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值