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);
        }
    }
}
相关推荐
元让_vincent4 小时前
AutoDL 上配置远程桌面运行 3DGS / SLAM 可视化:TurboVNC + XFCE + SSH 隧道完整可行流程
运维·3d·ssh
小清兔4 小时前
Addressable的设置打包流程
笔记·游戏·unity·c#
●VON5 小时前
纯ArkUI实现7层拟物3D环形进度图:零依赖的视觉革命
服务器·3d·app·鸿蒙·von
3D霸霸7 小时前
Sourcetree 拉取新工程
数据仓库·unity
阿斯加德D7 小时前
《霍格沃茨之遗》风灵月影修改器下载(已汉化)2026最新版
人工智能·测试工具·游戏·3d·游戏程序
在下胡三汉8 小时前
3dmax直接导入加载glb,gltf格式模型插件,支持导入动画材质贴图纹理,可以批量导入
3d·材质·贴图·gltf·glb
程序员正茂8 小时前
Unity3d中RawImage显示视频画面偏白的解决方法
unity·视频·rawimage
mxwin10 小时前
Unity SetPassCall和DrawCall的区别是什么
unity·游戏引擎·shader
电子云与长程纠缠11 小时前
UE5 GameFeature创建与使用
开发语言·学习·ue5·游戏引擎
ZPC821011 小时前
YOLO + 3D 空间定位 + 抓取姿态 完整方案
yolo·3d