自定义对象池实战:用 Dictionary + List 在 Unity 中实现高效的 GameObject 复用(Unity3DTraining Object Pool2 源码解析)
示例工程【免费下载链接】Unity3DTraining【Unity杂货铺】unity大杂烩~项目地址https://gitcode.com/gh_mirrors/un/Unity3DTraining点击查看免费下载本篇文章聚焦 Unity3DTraining 仓库中MemoryPool_ObjectPool/Object Pool2示例的完整实现它不依赖任何第三方插件仅用Dictionarystring, ListGameObject两个基础容器就写出了一套可复用的 GameObject 对象池。读完本文你将掌握对象池的借取Get/归还Store核心模型、预制体命名与 Key 匹配的底层细节并能在自己的射击、刷怪、弹幕等高频实例化场景中直接落地这套方案。文章配套源码与场景位于 MemoryPool_ObjectPool/Object Pool2同仓库还收录了一篇泛型对象池理论译文MemoryPool_ObjectPool/Object Pool两篇可对照阅读。图 1Game 运行视图白色小方块即是从对象池中重复借出/归还的子弹实例图 2Hierarchy 面板中Gun节点下挂载的多个bullet(Clone)实例正是对象池缓存未激活子弹的直接证据一、为什么需要对象池频繁实例化的性能账本在 Unity 中大量重复出现的物体——例如发射的子弹、爆炸特效、飘字——如果每次都走Instantiate/Destroy会造成两笔开销实例化/销毁的引擎开销创建与销毁 GameObject、挂载组件、分配本地内存均需时间成本托管堆压力每次实例化都会产生托管堆分配频繁分配会推高 GC 频率引发帧率抖动。对象池的基本思路在源码注释中写得很直白GameObjectPool.cs将用过的对象保存起来等下一次需要这种对象的时候再拿出来重复使用。恰当地使用对象池可以在一定程度上减少频繁创建对象所造成的开销。同时源码注释也给出了重要警示并非所有对象都适合池化。维护对象池本身也有开销如果对象生成成本很低池化反而可能使维护池的开销大于新建对象的开销导致性能不升反降。这一点是使用对象池前必须做的取舍判断。二、核心设计借Get与还Store两个静态方法整套池的对外接口只有两个静态方法职责单一方法职责对应时机GameObjectPool.Get(prefabName, position, rotation)从池中借出一个实例池空则新建发射子弹、生成敌人时GameObjectPool.Store(go)把用完的实例归还进池隐藏而非销毁子弹飞完、敌人死亡时内部存储结构GameObjectPool.csprivate static Dictionarystring, ListGameObject pool new Dictionarystring, ListGameObject();Key预制体的名字实际是实例化后的(Clone)名见下文ValueListGameObject存放该类型下所有已回收、未激活的实例。2.1 借取Get 的三条分支逻辑Get 方法 的完整实现public static GameObject Get(string prefabName, Vector3 position, Quaternion rotation) { // 拼接制作dic的key名因为instantiate出的gameobject都会自动命名为gameobject(Clone) // 这里是为了通下面store方法里给key的命名匹配 string key prefabName (Clone); GameObject go; // 如果字典里有这个key 并且key对应的数组不为空有该种类子弹且该种类子弹中有已经创建过的未激活的子弹 if (pool.ContainsKey(key) pool[key].Count 0) { // 从gameobjectname这个key位置取出数组 ListGameObject list pool[key]; // 取出一号位的子弹 go list[0]; // 从列表中去除这个子弹拿出来用 list.RemoveAt(0); // 初始化状态 go.SetActive(true); go.transform.position position; go.transform.rotation rotation; } // 如果对象池中没有对象 else { go Instantiate(Resources.Load(prefabName), position, rotation) as GameObject; } return go; }三个关键细节值得注意Key 拼接规则key prefabName (Clone)。因为 UnityInstantiate出来的对象会被自动命名为xxx(Clone)Store时直接取go.name作为 Key二者天然对齐。这是整套池能正确分类的前提复用时的状态重置从List[0]取出后要RemoveAt(0)随后重新设置SetActive(true)、position、rotation保证复用对象状态与新建对象一致池空的兜底路径直接Instantiate(Resources.Load(prefabName), position, rotation)。注意这里用Resources.Load所以预制体必须放在Resources目录下本示例位于 Assets/Resources/bullet.prefab。2.2 归还Store 的隐藏而非销毁策略Store 方法public static GameObject Store(GameObject go) { // 获取gameobject的名字会是一个在上面get方法里创建的预设体的gameobject名字会是gameobject(Clone) string key go.name; if (pool.ContainsKey(key)) { // 就在这个key所对应的数组中加入这个g // 这个g就是已经用完的子弹放到这个数组里的gameobject都是不销毁只是取消激活等待再次利用的gameobject pool[key].Add(go); } else { // 建立一个这个key的arraylist 并把g加进去 pool[key] new ListGameObject() { go }; } go.SetActive(false); return go; }归还的核心动作是SetActive(false)而非Destroy。隐藏后对象仍驻留内存等待下一次Get时被重新激活。Dictionary的ContainsKey分支保证了每种类型首次归还时自动创建对应的List无需预初始化。三、演示场景PoolTest 发射 AutoDestroy 自动回收3.1 触发端按空格借出子弹并施加冲量PoolTest.csvoid Update () { if (Input.GetKeyDown(KeyCode.Space)) { GameObject bullet GameObjectPool.Get(bullet, trans.position, Quaternion.identity); bullet.GetComponentRigidbody().AddForce(trans.forward*30, ForceMode.Impulse); } }trans是一个Transform字段指向枪口/发射点在 Inspector 中拖拽赋值Get(bullet, ...)传入的bullet正是Resources下预制体的名字不含扩展名借出的子弹立即被AddForce(trans.forward * 30, ForceMode.Impulse)以冲量方式赋予前向速度——这也解释了为什么子弹预制体需要挂Rigidbody。3.2 回收端3 秒后自动归还AutoDestroy.cs 挂在子弹预制体上实现用完自动回池void Update () { StartCoroutine(DestroySelf()); } private IEnumerator DestroySelf() { yield return new WaitForSeconds(3f); GameObjectPool.Store(this.gameObject); }逻辑一目了然子弹飞出 3 秒后调用GameObjectPool.Store(this.gameObject)将自己归还。配合图 2 的 Hierarchy 截图可以看到Gun节点下累积了 8 个bullet(Clone)正是这些归还后处于未激活缓存状态的实例。小提醒StartCoroutine放在Update里会每帧重复启动协程生产代码通常应改为在实例激活时启动一次本示例旨在演示回收思路读者接入自己项目时按需调整即可。四、对象池设计要点与进阶方向4.1 本方案的设计取舍可据此扩展从 GameObjectPool.cs 源码结构可以归纳出该方案的特征按类型分类缓存不同预制体通过 Key 自然隔离互不干扰静态访问pool与Get/Store均为static全局任意脚本可直接调用Awake中的_instance仅为演示预留的单例赋值实际逻辑并未依赖它无容量上限、无预热首次借取时新建后续回收复用实现极简线程模型依赖 Unity 主线程的Update/协程调用未做线程安全处理——这也是 Unity 对象池的常见形态与 MemoryPool_ObjectPool/Object Pool 中Unity 只有主线程可调用 API池无需支持多线程的结论一致。4.2 与泛型对象池的对照仓库的 Object Pool/README.md 提供了一份 C# 泛型对象池译文展示了面向普通 C# 类的池化思路StackTNew()/Store()、支持重置闭包ResetAction、按需初始化OnetimeInitAction、IResetable自重置、帧末集体重置ResetAll等进阶设计。两者互补泛型池管类实例本示例管场景 GameObject。前者适合ListVector3、自定义数据结构等内存敏感场景后者直接接管 GameObject 的生命周期与激活状态更适合射击、刷怪这类场景级高频复用。4.3 落地到真实项目时建议补充的能力预热与上限场景加载时为高频类型预先GetStore一批实例并设定单类型池容量上限避免峰值时大量新建重置钩子复用对象若有复杂状态血条、Buff、动画建议在Get时统一重置保证借出即干净场景切换清理Store进池的对象若在切换场景时被自动销毁需同步清空对应 Key 的缓存避免残留引用。五、总结Unity3DTraining 的Object Pool2示例用约 70 行代码完成了对象池的完整闭环Get借出池空则Resources.LoadInstantiate兜底→Store归还SetActive(false)隐藏缓存→ 以预制体名(Clone)作为字典 Key 分类管理。它证明了对象池的核心并不复杂关键在于复用的对象必须重置到可用状态以及缓存要按类型隔离。结合图 1、图 2 的运行效果你可以快速验证反复按空格发射子弹Hierarchy 中的bullet(Clone)数量不会无限增长因为飞出的子弹 3 秒后都会回到池中等待再次借出。若需要更理论化的对象池设计讨论重置策略、集体重置、容量收缩等可继续阅读 MemoryPool_ObjectPool/Object Pool/README.md并把它与本篇的 GameObject 版实现互为参照搭建出适合自己项目的完整内存优化方案。赞分享示例工程【免费下载链接】Unity3DTraining【Unity杂货铺】unity大杂烩~项目地址https://gitcode.com/gh_mirrors/un/Unity3DTraining点击查看免费下载相关推荐BMAD-METHOD 官方模块体系解析bmb / cis / gds / tea 四大模块、安装器分发机制与版本通道BMAD METHOD 官方模块体系解析bmb / cis / gds / tea 四大模块、安装器分发机制与版本通道 BMAD METHOD 的核心功能由内AI 技能人工智能开发工具Gonum内存池实现sync.Pool在矩阵对象复用中的应用Gonum内存池实现sync.Pool在矩阵对象复用中的应用 在数值计算领域频繁创建和销毁矩阵对象会导致严重的性能损耗和内存碎片化。Gonum作为Go语言的科学计算在 Garnet 中开发自定义对象Custom Object从继承 CustomObjectBase 到注册自定义命令的完整实战在 Garnet 中开发自定义对象Custom Object从继承 CustomObjectBase 到注册自定义命令的完整实战 导读 Garnet 是缓存KV存储后端上一篇mikro-orm 虚拟实体Virtual Entities实战用动态 SQL 与 MongoDB 聚合映射只读实体下一篇探索TelegraphiOS、tvOS和macOS的安全Web服务器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

mikro-orm 虚拟实体(Virtual Entities)实战:用动态 SQL 与 MongoDB 聚合映射只读实体

mikro-orm 虚拟实体(Virtual Entities)实战:用动态 SQL 与 MongoDB 聚合映射只读实体

后端 【免费下载链接】mikro-orm TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, MariaDB, MS SQL Server, PostgreSQL and SQLite/libSQL databases. 项目地址: https://gitcode.com/gh_mir…

2026/9/25 5:13:02 阅读更多 →
Atlas 300V 24G推理加速卡实测:YOLOv5部署全链路与调优

Atlas 300V 24G推理加速卡实测:YOLOv5部署全链路与调优

接到手这块Atlas 300V 24G的时候,我第一反应也是去查它到底算运算加速卡还是别的什么卡。等真正把YOLOv5跑起来,又折腾了一阵驱动和模型转换之后,才发现网上一堆帖子说得云里雾里。这篇文章就围绕两个高频问题来写:Atlas 300V 24G…

2026/9/25 5:13:02 阅读更多 →
Cursor新模型Composer来了,TaoToken统一Key怎么接?

Cursor新模型Composer来了,TaoToken统一Key怎么接?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 5:13:02 阅读更多 →

最新新闻

多协议支持实战:用 LiteLLM 让一个模型同时讲 OpenAI、Responses 和 Anthropic 三种“方言”并接入 TaoToken

多协议支持实战:用 LiteLLM 让一个模型同时讲 OpenAI、Responses 和 Anthropic 三种“方言”并接入 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 8:22:38 阅读更多 →
LibreChat:多模型统一自托管AI聊天平台部署指南

LibreChat:多模型统一自托管AI聊天平台部署指南

我是在整理自托管服务清单时注意到 LibreChat 的,一开始没当回事,后来发现身边好几个搞技术朋友都在用,才认真研究了一下。这个项目本质上是一个开源的 AI 聊天客户端,但它解决了一个挺麻烦的问题:不同 AI 模型散落在各…

2026/9/25 8:22:38 阅读更多 →
vinext 兼容性压力测试实战:用 pages-router-complex 演练大型 Pages Router 企业应用迁移

vinext 兼容性压力测试实战:用 pages-router-complex 演练大型 Pages Router 企业应用迁移

后端Web框架SSR 【免费下载链接】vinext Vite plugin that reimplements the Next.js API surface — deploy anywhere 项目地址: https://gitcode.com/gh_mirrors/vi/vinext 点击查看 免费下载 导读:pages-router-complex 是 vinext(基于 V…

2026/9/25 8:22:38 阅读更多 →
BentoML 流式响应实战:LLM 文本流、音频字节流与服务端流式实现解析

BentoML 流式响应实战:LLM 文本流、音频字节流与服务端流式实现解析

模型推理服务人工智能后端大模型MLOpsLLMOps 【免费下载链接】BentoML The easiest way to serve AI apps and models - Build Model Inference APIs, Job queues, LLM apps, Multi-model pipelines, and more! 项目地址: https://gitcode.com/gh_mirrors/be/BentoM…

2026/9/25 8:22:38 阅读更多 →
Hugo Blox Builder 简历页实战:用 resume 系列 Blox 组装 Experience / Skills / Awards / Languages 履历页面

Hugo Blox Builder 简历页实战:用 resume 系列 Blox 组装 Experience / Skills / Awards / Languages 履历页面

静态站点前端开发工具 【免费下载链接】kit 🧱 Describe your site, AI builds it, you own it as Markdown. Snap together Tailwind blocks like Lego — landing pages, blogs, portfolios, docs & more. No AI slop. Free to deploy anywhere 👇…

2026/9/25 8:22:38 阅读更多 →
React.cache() 请求内去重指南:服务端认证与数据库查询的 RSC 性能优化(mediago Vercel React 最佳实践)

React.cache() 请求内去重指南:服务端认证与数据库查询的 RSC 性能优化(mediago Vercel React 最佳实践)

音视频桌面应用后端 【免费下载链接】mediago 跨平台视频提取工具:支持流媒体下载、视频下载、m3u8 下载及 B站视频下载,提供 Windows 和 Mac 桌面客户端。Cross-platform video extraction tool: Supports streaming download, video download, m3u8 do…

2026/9/25 8:21:38 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →