Complex nested object pool (2) - object pool that manages a single instance object

[Object pool interface]

According to the data and operations required by the object pool, first define the basic interface

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

The operation methods are lending objects and reclaiming objects.

When lending an object, you need to pass in the object name to identify which object you want to lend; parent indicates who is the parent object of the object to be lent; and there is also a default parameter array.

[Object pool base class]

The key data to be counted is the total number of generated instance objects, the total number of cached instance objects, and the total number of cacheable instance objects. 

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;
        }
      
    }
}

[Object pool that manages instance objects of a single source object]

We know that all objects in an object pool are instance objects of a source object, that is, when go = UnityEngine.Object.Instantiate(SourceGo,parent) is called, a series of go is stored in the object pool, and Source is our Said source object, this source object should be obtained by loading. The object pool manages the instance object, not the source object, and the two should be managed separately.

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);
        }

    }

}

[Management of source objects]

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;
        }
    }
}

Guess you like

Origin blog.csdn.net/enternalstar/article/details/125173416