复杂嵌套的对象池(2)——管理单个实例对象的对象池

【对象池接口】

根据对象池所需要的数据和操作,先定义基本的接口

public interface IObjectPool : ICountable, IShrinkable, IDisposable
    {
        GameObject LendObjectOut(string objectName, Transform parent = null,params object[] extradata);
        bool RecycleObject(GameObject go);
    }

操作方法为借出对象和回收对象。

借出对象时要传入对象名字,标识想借出哪个对象;parent表示要借出的这个对象的父对象是谁;同时还有个缺省的参数数组。

【对象池基类】

要统计的关键数据是生成的实例对象总数,缓存的实例对象总数,可缓存的实例对象总数。 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace Cache
{
    public interface IObjectPool : ICountable, IShrinkable, IDisposable
    {
        GameObject LendObjectOut(string objectName, Transform parent = null,params object[] extradata);
        bool RecycleObject(GameObject go);
    }

    public  class ObjectPoolBase : IObjectPool
    {
        /// <summary>
        /// 生成的实例对象总数
        /// </summary>
        public int TotalCount { get; protected set; }
        /// <summary>
        /// 缓存的实例对象总数
        /// </summary>
        public int CachedCount { get; protected set; }
        /// <summary>
        /// 可缓存的实例对象容量
        /// </summary>
        public virtual int TotalCapcity { get; protected set; }

        protected ICache poolCache;
        /// <summary>
        /// 对象池名字
        /// </summary>
        protected string poolName;
        /// <summary>
        /// 对象池容量大小
        /// </summary>
        protected int capacity;

        protected Action<bool> onlendObjectOut;

        protected Action<bool> onRecycleObject;

        public virtual int Capacity()
        {
            return poolCache.Capacity();
        }

        public virtual int Count()
        {
            return poolCache.Count();
        }

        public virtual void Dispose()
        {
            poolCache.Dispose();
        }

        public virtual bool Shrink(ShrinkStrategy shrinkStrategy, float percent, int count, bool weedout)
        {
            return poolCache.Shrink(shrinkStrategy, percent, count, weedout);
        }

        public virtual GameObject LendObjectOut(string objectName, Transform parent = null, params object[] extradata)
        {
            return null;
        }

        public virtual bool RecycleObject(GameObject go)
        {
            return false;
        }
      
    }
}

【管理单个源对象的实例对象的对象池】

我们知道一个对象池里的所有对象都是某个源对象的实例对象,也即调用go = UnityEngine.Object.Instantiate(SourceGo,parent)时,对象池里存放的是一系列go,而Source是我们说的源对象,这个源对象应该通过加载来获取。对象池管理的是实例对象,而不是源对象,两者要分开管理。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace Cache
{
    public class SingleObjectPool:ObjectPoolBase
    {
        private FIFO<GameObject> _poolCache;
        private ExpansionStrategy expansionStrategy;

        //重写可缓存实例对象的get方法,其在缩容时其会改变
        public override int TotalCapcity { get => _poolCache.Capacity(); protected set => TotalCapcity = value; }

        public SingleObjectPool(int capacity,string poolName, ExpansionStrategy expansionStrategy = ExpansionStrategy.NONE, Action<bool> onlendObjectOut = null, Action<bool> onRecycleObject = null) 
        {
            poolCache = new FIFO<GameObject>(capacity, expansionStrategy, OnWeedOut);
            _poolCache = poolCache as FIFO<GameObject>;
           
            this.capacity = capacity;
            this.poolName = poolName;
            this.expansionStrategy = expansionStrategy;
            this.onlendObjectOut = onlendObjectOut;
            this.onRecycleObject = onRecycleObject;
        }

        public override GameObject LendObjectOut(string objectName,Transform parent = null, params object[] extradata)
        {
            if(string.IsNullOrEmpty(objectName))
                return null;

            if (!objectName.Equals(poolName))//如果要借出的物体名字和当前对象池名字不同,说明不能从当前对象池中借出对象
                return null;

            GameObject go = null;
            if(_poolCache.Get(out go))//先从池子里面获取
            {
                CachedCount--;//缓存对象减少
                onlendObjectOut?.Invoke(false);
                if(parent != null)
                    go.transform.SetParent(parent);
                return go;
            }

            //没有就实例化一个,获取一个源对象来实例化
            go = UnityEngine.Object.Instantiate(SourceGameObjectMap.GetSourceGameObject(objectName),parent);

            if (go != null)
            {
                TotalCount++;//实例对象增加
                onlendObjectOut?.Invoke(true);
            }
            return go;
        }

        public override bool RecycleObject(GameObject go)
        {
            if(_poolCache.Put(go))
            {
                CachedCount++;//缓存对象增加
                onRecycleObject?.Invoke(false);
                return true;
            }
            return false;
        }

        protected void OnWeedOut(GameObject go)//如果淘汰则销毁
        {
            if (go == null)
                return;
           
            go.transform.SetParent(null); //防止因为Destroy慢一帧依然被GetComponentsInChildren获取到
            GameObject.Destroy(go);
            TotalCount--;//销毁时,缓存的和生成的实例对象数量都减小
            CachedCount--;
            onRecycleObject?.Invoke(true);
        }

    }

}

【源对象的管理】

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Cache
{
    public class SourceGameObjectMap
    {
        public static Dictionary<string, GameObject> map = new Dictionary<string, GameObject>();

        public static GameObject GetSourceGameObject(string objectName)
        {
            if(map.TryGetValue(objectName, out GameObject go))
            {
                return go;
            }
            go = Resources.Load<GameObject>(objectName);//先简单的用Resources.Load,可以自己改为用AB或AA
            map.Add(objectName, go);
            return go;
        }

        public static bool UnlaodSourceGameObject(string objectName)
        {
            if(map.TryGetValue(objectName, out GameObject go))
            {
                map.Remove(objectName);
                Resources.UnloadAsset(go);
                return true;
            }
            return false;
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值