Unity MyFramework 用法说明(十):使用 ClassObject 和 ClassScope 管理可复用对象
上一篇介绍 EventSystem 时带参数事件通过ClassScope创建using var a new ClassScopeEventLocationChanged(out var param);ClassScope背后使用的是 MyFramework 的ClassPool。它不仅能减少高频创建临时对象产生的 GC也为普通 C# 对象提供了一套统一的创建、重置和销毁流程。项目地址https://github.com/ZHOURUIH/MyFramework一、为什么需要 ClassPool游戏运行过程中会频繁创建各种临时对象例如事件参数 技能参数 子弹参数 网络消息 状态机参数 伤害数字数据 临时查询结果直接使用new创建这些对象EventLocationChanged param new EventLocationChanged();使用结束后只能等待 GC 回收。当创建频率较高时大量短生命周期对象会持续产生托管内存分配最终引起 GC。MyFramework 的处理方式是从 ClassPool 获取对象 ↓ 使用对象 ↓ 将对象归还 ClassPool ↓ 下次继续复用要加入这套对象池体系类需要继承ClassObject。二、创建一个 ClassObject以项目中的拍卖物品数据为例public class AuctionItem : ClassObject { protected long mInstanceID; protected int mTimeMinute; protected int mPrice; protected int mAveragePrice; public void setInstanceID(long instanceID) { mInstanceID instanceID; } public void setTime(int timeMinute) { mTimeMinute timeMinute; } public void setPrice(int price) { mPrice price; } public void setAveragePrice(int price) { mAveragePrice price; } public long getInstanceID() { return mInstanceID; } public int getTime() { return mTimeMinute; } public int getPrice() { return mPrice; } public int getAveragePrice() { return mAveragePrice; } public override void resetProperty() { base.resetProperty(); mInstanceID 0; mTimeMinute 0; mPrice 0; mAveragePrice 0; } }resetProperty()非常重要。对象归还对象池时框架会调用它清理数据。下次重新取出同一个实例时不应该保留上一次使用的状态。所以继承ClassObject后所有字段都应该在这里重置public override void resetProperty() { base.resetProperty(); mTarget null; mCount 0; mPosition Vector3.zero; mFinished false; }遗漏任何字段都可能导致复用对象时读取到旧数据。三、使用 CLASS 创建长期对象通过CLASST()从对象池获取对象using static FrameUtility; AuctionItem item CLASSAuctionItem(); item.setInstanceID(instanceID); item.setTime(timeMinute); item.setPrice(price); item.setAveragePrice(averagePrice);实际项目中的AuctionSystem会把拍卖物品长期保存在字典中using System.Collections.Generic; using static FrameUtility; public class AuctionSystem : FrameSystem { protected Dictionarylong, AuctionItem mAuctionList new(); public AuctionItem createAuctionItem( long instanceID, int timeMinute, int price, int averagePrice) { if (!mAuctionList.getOrAddClass( instanceID, out AuctionItem item)) { item.setInstanceID(instanceID); item.setTime(timeMinute); item.setPrice(price); item.setAveragePrice(averagePrice); } return item; } }CLASST()创建的是需要手动管理生命周期的对象。只要业务仍然持有这个对象它就不会自动归还对象池。四、使用 UN_CLASS 回收对象拍卖物品失效后通过UN_CLASS回收public void destroyAuction(long instanceID) { mAuctionList.Remove( instanceID, out AuctionItem auction); UN_CLASS(ref auction); }推荐传入refUN_CLASS(ref auction);回收完成后框架会同时把当前变量设置为null减少继续误用该引用的可能性。对象回收过程大致为标记对象正在销毁 ↓ 调用 destroy() ↓ 调用 resetProperty() ↓ 放回未使用队列下一次调用CLASSAuctionItem()时就可以直接取出这个对象继续使用。五、回收对象集合如果一个列表中的元素全部来自ClassPool可以统一回收protected ListAuctionItem mAuctionList new(); public override void destroy() { UN_CLASS_LIST(mAuctionList); base.destroy(); }UN_CLASS_LIST会逐个回收列表中的 ClassObject 清空列表它支持常见集合ListT HashSetT DictionaryTKey, TValue QueueT例如销毁全部子弹public void destroyAllBullet() { UN_CLASS_LIST(mBulletList.getMainList()); mBulletList.clear(); }注意集合本身不会因此变成null只是其中的对象被回收并清空。六、使用 ClassScope 创建临时对象有些对象只在当前代码块中临时使用例如事件参数public class EventLocationChanged : GameEvent { public Vector2Int mLastTilePosition; public Vector2Int mTilePosition; public override void resetProperty() { base.resetProperty(); mLastTilePosition Vector2Int.zero; mTilePosition Vector2Int.zero; } }发送事件时使用ClassScopeusing var a new ClassScopeEventLocationChanged( out var param); param.mLastTilePosition lastTilePosition; param.mTilePosition newTilePosition; mEventSystem.pushEvent(param);离开当前作用域时ClassScope.Dispose()会自动将对象归还对象池。完整流程是进入作用域 ↓ 从 ClassPool 获取 EventLocationChanged ↓ 填写事件参数并发送 ↓ 离开作用域 ↓ 自动归还对象池不需要再手动调用UN_CLASS(ref param);对于明确只在当前作用域使用的临时对象优先使用ClassScope可以避免忘记回收。七、不能保存 ClassScope 中的对象下面的写法是错误的protected EventLocationChanged mLastEvent; public void sendEvent() { using var a new ClassScopeEventLocationChanged(out var param); mLastEvent param; mEventSystem.pushEvent(param); }离开sendEvent()后param已经被归还对象池。但mLastEvent仍然保存着它的引用。这个实例随后可能被其他逻辑重新取出并修改。因此ClassScope中的对象只能在当前作用域内使用可以立即读取 可以传给同步执行的函数 不能保存到成员变量 不能放进长期存在的集合 不能在作用域结束后继续访问如果对象需要长期保存应使用CLASST()创建并在生命周期结束时通过UN_CLASS回收。八、ClassObject 的生命周期ClassObject主要包含三个生命周期函数public virtual void onCreate() { } public virtual void destroy() { } public virtual void resetProperty() { base.resetProperty(); }它们的职责不同。onCreate每次对象从池中分配出来时调用public override void onCreate() { base.onCreate(); // 每次开始使用对象时执行 }无论对象是第一次创建还是从池中复用都会执行。destroy对象归还对象池前调用public override void destroy() { // 注销事件、解除外部关联等 base.destroy(); }适合处理具有行为意义的清理例如取消事件监听 解除管理器引用 移出其他容器 释放关联资源resetProperty负责将所有字段恢复到默认状态public override void resetProperty() { base.resetProperty(); mOwner null; mID 0; mData null; }它不负责业务逻辑只负责保证对象下次使用时是干净的。九、不要依赖构造函数重复初始化对象池复用时不会再次调用构造函数。下面的写法只能在对象第一次被new出来时执行public AuctionItem() { mTimeMinute 10; }对象回收后重新获取不会再次进入构造函数。需要每次分配时执行的逻辑应放在public override void onCreate() { base.onCreate(); }需要清理的字段应放在public override void resetProperty() { base.resetProperty(); }ClassPool 也不支持依赖带参数构造函数创建对象因为对象复用时无法重新传入构造参数。十、主线程和子线程对象池普通接口CLASST(); UN_CLASS(ref obj);使用的是主线程ClassPool不能在子线程中调用。子线程需要使用MyData data CLASS_THREADMyData(); UN_CLASS_THREAD(ref data);主线程对象池和线程对象池彼此独立不应该混合创建和回收。也就是CLASS 创建的对象 必须由 UN_CLASS 回收 CLASS_THREAD 创建的对象 必须由 UN_CLASS_THREAD 回收十一、CLASS 和 ClassScope 如何选择长期保存的业务对象AuctionItem item CLASSAuctionItem(); mAuctionList.Add(item.getInstanceID(), item);生命周期结束时手动回收UN_CLASS(ref item);只在当前代码块使用的临时对象using var a new ClassScopeEventLocationChanged( out var param);选择规则可以概括为需要跨函数或长期保存 使用 CLASS UN_CLASS 只在当前作用域临时使用 使用 ClassScope十二、总结MyFramework 的 ClassPool 用法主要包括1. 可复用对象继承 ClassObject 2. 在 resetProperty 中重置全部字段 3. 使用 CLASS 获取长期对象 4. 使用 UN_CLASS 手动回收 5. 使用 UN_CLASS_LIST 批量回收 6. 使用 ClassScope 管理临时对象 7. 不要保存已经离开作用域的临时对象 8. 子线程使用 CLASS_THREAD对象池不只是把new换成CLASS。真正重要的是为普通对象建立清晰的生命周期创建或复用 ↓ 初始化并使用 ↓ 销毁业务关联 ↓ 重置全部状态 ↓ 等待下一次复用只有正确实现创建、使用和回收流程对象复用才能在减少 GC 的同时保持数据安全。

相关新闻

性价比高的上海全飞秒pro增强版哪家术后跟踪好

性价比高的上海全飞秒pro增强版哪家术后跟踪好

随着全飞秒激光手术技术的不断进步,越来越多的近视患者选择通过这种微创、恢复快且视觉质量高的方法来矫正视力。然而,在众多提供全飞秒服务的眼科医院中,如何选择一家不仅术前准备充分、手术过程精准高效,而且术后跟踪服务完善可…

2026/7/18 22:18:52阅读更多 →
Java大厂面经:Spring Cloud微服务+MCP+Agentic RAG三连问,水货程序员谢飞机大型翻车现场

Java大厂面经:Spring Cloud微服务+MCP+Agentic RAG三连问,水货程序员谢飞机大型翻车现场

Java大厂面经:Spring Cloud微服务MCPAgentic RAG三连问,水货程序员谢飞机大型翻车现场🎬 前言江湖传闻,有一号人物,姓谢,名飞机,Java圈内人称「八股文朗诵艺术家」——简单问题倒背如流&#xf…

2026/7/18 22:16:52阅读更多 →
鸿蒙 ArkTS 实战:Live Stream Script Helper 从智能助手到保存闭环完整解析

鸿蒙 ArkTS 实战:Live Stream Script Helper 从智能助手到保存闭环完整解析

鸿蒙 ArkTS 实战:Live Stream Script Helper 从智能助手到保存闭环完整解析 前言 Live Stream Script Helper 是一个面向 直播脚本助手 的鸿蒙 ArkTS 单页工具。它把主题输入、数量统计、辅助开关、备注和保存状态组织到一个移动端工作台中。 项目服务于 围绕商品…

2026/7/18 22:16:51阅读更多 →
HNU 湖南大学 系统编程与创新设计 2026BSP中期验收

HNU 湖南大学 系统编程与创新设计 2026BSP中期验收

1. (论述题, 100.0 分)步进电机: 1号电机正转40步(速度:每秒10步) 震动:震动后,蜂鸣器发出2次“叮咚”声(叮1.2KHz,咚500Hz)。#include "STC15F2K60S2.H" #include "sys.H" #include "StepMotor.h"code unsigned long S…

2026/7/18 23:47:03阅读更多 →
别再瞎喂提示词!ChatGPT情感故事产出率暴跌63%的5个隐藏陷阱(含真实会话日志还原)

别再瞎喂提示词!ChatGPT情感故事产出率暴跌63%的5个隐藏陷阱(含真实会话日志还原)

更多请点击: https://codechina.net 第一章:情感故事生成失效的警讯:63%产出率暴跌背后的真相 当模型在情感故事生成任务中突然从92%的稳定产出率骤降至34%,这并非偶然波动,而是系统性退化的明确信号。我们通过日志回…

2026/7/18 23:47:03阅读更多 →
紧急修复通知:Cursor搜索突然失效的4类Runtime Conflict场景(Node.js版本锁、WebAssembly加载失败、TS Server隔离崩溃)及3分钟热修复方案

紧急修复通知:Cursor搜索突然失效的4类Runtime Conflict场景(Node.js版本锁、WebAssembly加载失败、TS Server隔离崩溃)及3分钟热修复方案

更多请点击: https://intelliparadigm.com 第一章:Cursor搜索功能失效的紧急响应机制 当 Cursor 编辑器中全局搜索(Ctrl/CmdShiftF)或文件内搜索(Ctrl/CmdF)突然无响应、返回空结果或卡在“Searching…”状…

2026/7/18 23:47:03阅读更多 →
2026完整指南:AI辅助学术论文写作全流程,从选题到定稿避坑(附成品论文资源下载)

2026完整指南:AI辅助学术论文写作全流程,从选题到定稿避坑(附成品论文资源下载)

2026完整指南:AI辅助学术论文写作全流程,从选题到定稿避坑(附成品论文资源下载) 前言 每到毕业季、期刊投稿季,大量科研人、学生都会陷入论文写作困境:选题无思路、文献梳理耗时长、行文逻辑混乱、英文润…

2026/7/18 23:47:03阅读更多 →
AWS崩了、Azure崩了、Cloudflare也崩了……我悟出一个道理

AWS崩了、Azure崩了、Cloudflare也崩了……我悟出一个道理

一、巨头也会“掉链子” 如果你还觉得大厂的云服务稳如泰山,最近一年的几次全球性宕机事件可能会让你重新考虑。据媒体统计,仅在2025年下半年到2026年初,亚马逊AWS、微软Azure、Cloudflare就先后出现过大规模服务中断:AWS一次故障…

2026/7/18 23:47:03阅读更多 →
大模型想要稳定应用,离不开训练与推理两套算力体系

大模型想要稳定应用,离不开训练与推理两套算力体系

生成式 AI 掀起新一轮数字产业变革,智能算力从前沿概念转变为实体经济刚需。纵观整个 AI 算力产业链,两大趋势清晰可见:一是高密度智算集群持续规模化建设;二是算力商业模式持续迭代,Token标准化服务快速普及&#xff…

2026/7/18 23:45:03阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/18 10:49:13阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/18 8:49:08阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/18 14:49:24阅读更多 →
从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

更多请点击: https://kaifayun.com 第一章:从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档(PRD)生成实践中,原始业务意图往往以自然语言片…

2026/7/18 0:00:14阅读更多 →
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

更多请点击: https://codechina.net 第一章:Cursor配置生成失效?3大隐藏陷阱4行修复代码,资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效,是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…

2026/7/18 0:00:14阅读更多 →
某智驾大牛创业

某智驾大牛创业

作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…

2026/7/18 0:00:14阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/18 22:49:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/18 14:49:24阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/18 18:49:35阅读更多 →