Unity 3D 简易对象池

  • 依赖于UniTask(访问Github)
  • 依赖于Addressable资源管理(通过UPM安装)
csharp 复制代码
using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;


namespace EasyAVG
{

    public class Pool
    {

        public Action<GameObject> OnGet { get; set; } = defaultGet;
        public Action<GameObject> OnSet { get; set; } = defaultSet;
        public Action<GameObject> OnDestroy { get; set; } = defaultDestroy;

        public Action<GameObject> OnCreate { get; set; } = null;

        public int MaxCount { get; set; } = int.MaxValue;

        public int MinCount { get; set; } = 0;

        public string Location { get; set; } = null;





        private Queue<GameObject> queue = new Queue<GameObject>();


        static readonly Action<GameObject> defaultGet = (x) =>
            {
                x.SetActive(true);
            }
        , defaultSet = (x) =>
        {
            x.SetActive(false);
        }
        , defaultDestroy = (x) =>
        {
            GameObject.Destroy(x);
        };



        internal bool _destroyed = false;
        private IEnumerator PoolThread()
        {

            //cacheHandle = Addressables.LoadAssetAsync<GameObject>(Location);
            //yield return cacheHandle;
            while (true)
            {
                if (_destroyed)
                {
                    yield break;
                }
                if (MinCount > MaxCount) throw new InvalidOperationException($"Please keep MaxCount>MinCount . CurrentMin{MinCount}>CurreentMax{MaxCount}");
                if (queue.Count < MinCount)
                {

                    var handle = Addressables.InstantiateAsync(Location);
                    yield return handle;
                    OnCreate?.Invoke(handle.Result);
                    queue.Enqueue(handle.Result);
                }
                if (queue.Count > MaxCount)
                {
                    OnDestroy?.Invoke(queue.Dequeue());
                }
                yield return null;

            }

        }
        internal void InitPool()
        {
            PoolManager.Instance.StartCoroutine(PoolThread());
        }


        public async UniTask<GameObject> Get()
        {
            if (queue.Count == 0)
            {
                var handle = Addressables.InstantiateAsync(Location);
                await handle;
                OnCreate?.Invoke(handle.Result);
                OnGet?.Invoke(handle.Result);
                return handle.Result;
            }
            await UniTask.CompletedTask;
            var item = queue.Dequeue();
            OnGet?.Invoke(item);
            return item;
        }
        public GameObject GetSync()
        {
            if (queue.Count == 0)
            {
                var handle = Addressables.InstantiateAsync(Location);
                OnCreate?.Invoke(handle.Result);
                OnGet?.Invoke(handle.Result);
                return handle.Result;
            }
            var item = queue.Dequeue();
            OnGet?.Invoke(item);
            return item;
        }

        public void Set(GameObject item)
        {
            if (queue.Count >= MaxCount)
            {
                OnSet?.Invoke(item);
                OnDestroy?.Invoke(item);
                return;
            }
            else
            {
                OnSet?.Invoke(item);
                queue.Enqueue(item);
            }
        }

    }
}
csharp 复制代码
using Cysharp.Threading.Tasks;
using EasyAVG;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace EasyAVG
{

    public class PoolManager :MonoSingleton<PoolManager>
    {
    

        void OnDestroy()
        {
            foreach (var kvp in pools)
            {
                kvp.Value._destroyed = true;
            }
            pools.Clear();
        }

    



        private readonly Dictionary<string, Pool> pools = new Dictionary<string, Pool>();


        /// <summary>
        /// 创建对象池
        /// </summary>
        /// <param name="key"></param>
        /// <param name="location"></param>
        /// <param name="minCount"></param>
        /// <param name="maxCount"></param>
        public void CreatePool(string key, string location, int minCount = 0, int maxCount = int.MaxValue
         )
        {
            if (pools.ContainsKey(key)) return;
            Pool pool = new Pool();

            pool.Location = location;
            pool.MinCount = minCount;
            pool.MaxCount = maxCount;
            pools.Add(key, pool);

            pool.InitPool();
        }


        /// <summary>
        /// 获取对象池
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Pool GetPool(string key)
        {
            if (!pools.ContainsKey(key)) return null;
            return pools[key];
        }


        /// <summary>
        /// 销毁对象池
        /// </summary>
        /// <param name="key"></param>
        /// <param name="exThrow"></param>
        /// <exception cref="NullReferenceException"></exception>
        public void DestroyPool(string key, bool exThrow = false)
        {
            if (!pools.ContainsKey(key))
            {
                if (exThrow)
                    throw new NullReferenceException("Destroying non-existent pool is not allowed");
                else return;
            }
            pools[key]._destroyed = true;
            pools.Remove(key);
        }


        /// <summary>
        /// 异步获取对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public UniTask<GameObject> GetAsync(string key)
        {
            var pool = GetPool(key) ?? throw new InvalidOperationException("Please get after create pool");
            return pool.Get();
        }

        /// <summary>
        /// 同步获取对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public GameObject GetSync(string key)
        {
            var pool = GetPool(key) ?? throw new InvalidOperationException("Please get after create pool");
            return pool.GetSync();
        }

        /// <summary>
        /// 放回对象
        /// </summary>
        /// <param name="key"></param>
        /// <param name="obj"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void Recycle(string key, GameObject obj)
        {
            var pool = GetPool(key) ?? throw new InvalidOperationException("Please set after create pool");
            pool.Set(obj);
        }

        /// <summary>
        /// 异步获取组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public async UniTask<T> GetComponentAsync<T>(string key) where T : Component
        {
            var pool = GetPool(key);
            return (await pool.Get()).GetComponent<T>();
        }

        /// <summary>
        /// 同步获取组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetComponentSync<T>(string key) where T : Component
        {
            var pool = GetPool(key);
            return pool.GetSync().GetComponent<T>();
        }

        /// <summary>
        /// 同步回收组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="com"></param>
        public void RecycleComponent<T>(string key, T com) where T : Component
        {
            var pool = GetPool(key);
            pool.Set(com.gameObject);
        }
    }
}
相关推荐
red_redemption40 分钟前
自由学习记录(23)
学习·unity·lua·ab包
/**书香门第*/4 小时前
Cocos creator 3.8 支持的动画 7
学习·游戏·游戏引擎·游戏程序·cocos2d
向宇it18 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
Heaphaestus,RC20 小时前
【Unity3D】获取 GameObject 的完整层级结构
unity·c#
芋芋qwq20 小时前
Unity UI射线检测 道具拖拽
ui·unity·游戏引擎
tealcwu21 小时前
【Unity服务】关于Unity LevelPlay的基本情况
unity·游戏引擎
大眼睛姑娘1 天前
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
unity·游戏美术
前端Hardy1 天前
HTML&CSS:数据卡片可以这样设计
前端·javascript·css·3d·html
鹿野素材屋1 天前
Unity Dots下的动画合批工具:GPU ECS Animation Baker
unity·游戏引擎
小彭努力中1 天前
138. CSS3DRenderer渲染HTML标签
前端·深度学习·3d·webgl·three.js