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);
        }
    }
}
相关推荐
神码编程4 小时前
【Unity功能集】TextureShop纹理工坊(五)选区
unity·游戏引擎·shader·ps选区
m0_748251729 小时前
Android webview 打开本地H5项目(Cocos游戏以及Unity游戏)
android·游戏·unity
benben04410 小时前
Unity3D仿星露谷物语开发7之事件创建动画
unity·游戏引擎
十年一梦实验室12 小时前
【C++】sophus : rxso3.hpp 实现了 3D 空间中的旋转和缩放操作的 RxSO3 类 (二十一)
开发语言·c++·人工智能·算法·3d
林枫依依12 小时前
Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉
unity
虾球xz13 小时前
游戏引擎学习第57天
学习·游戏引擎
逆旅行天涯14 小时前
【Threejs】从零开始(六)--GUI调试开发3D效果
前端·javascript·3d
异次元的归来1 天前
Unity DOTS中的share component
unity·游戏引擎
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
_oP_i1 天前
unity webgl部署到iis报错
unity