# 资源管理扩展 **本文档引用的文件** - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs) - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs) - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs) - [UnRegisterListExtensionTests.cs](file://GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖分析](#依赖分析) 7. [性能考虑](#性能考虑) 8. [故障排除指南](#故障排除指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件围绕资源管理扩展展开,重点阐述 UnRegisterExtension 提供的资源清理与生命周期管理能力,包括自动资源释放、事件监听器注销、订阅关系清理以及内存泄漏防护等核心功能。文档将结合具体代码文件,说明各类资源清理方法的使用场景与调用时机,并给出最佳实践指导,帮助开发者在游戏开发中实现稳定、高性能、低泄漏的资源管理。 ## 项目结构 资源管理扩展主要分布在以下模块: - 抽象层:定义统一的注销接口与列表接口,确保跨平台一致性 - 核心实现:提供默认注销器、注销列表、事件系统与组合事件等 - 平台扩展:Godot 平台下的节点生命周期绑定扩展 - 测试:验证扩展方法的行为与边界条件 ```mermaid graph TB subgraph "抽象层" IUR["IUnRegister 接口"] IURL["IUnRegisterList 接口"] end subgraph "核心实现" DUR["DefaultUnRegister 实现"] URL["UnRegisterList 列表"] Evt["EasyEvent 事件"] EBus["EventBus 总线"] EAll["EasyEvents 全局管理"] OREvt["OrEvent 组合事件"] end subgraph "平台扩展" URExt["UnRegisterExtension 扩展"] SigExt["SignalFluentExtensions 信号扩展"] end IUR --> DUR IURL --> URL EBus --> EAll EBus --> Evt OREvt --> IURL URExt --> IUR SigExt --> URExt ``` **图表来源** - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22) **章节来源** - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22) ## 核心组件 - IUnRegister:定义统一的注销接口,要求实现 UnRegister() 方法以执行清理动作 - DefaultUnRegister:默认注销器实现,保存回调并在注销时调用并清理引用 - IUnRegisterList:统一注销列表接口,暴露可变的 IUnRegister 集合 - UnRegisterList:注销列表实现,提供批量注销与清空能力 - UnRegisterListExtension:扩展方法,提供 AddToUnregisterList 与 UnRegisterAll 的便捷调用 - EasyEvent:简单事件系统,注册回调返回 IUnRegister,支持触发与注销 - EventBus:类型化事件总线,封装 EasyEvents,提供 Send/Register/UnRegister - OrEvent:组合事件,支持多事件“或”逻辑,内部维护注销列表 - UnRegisterExtension(Godot):将 IUnRegister 与 Godot 节点生命周期绑定,节点退出场景树时自动注销 - SignalFluentExtensions(Godot):为 Node 提供信号流畅 API,便于与注销机制配合 **章节来源** - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22) ## 架构总览 资源管理扩展通过“接口抽象 + 默认实现 + 扩展方法 + 平台绑定”的方式,形成清晰的层次化架构: - 抽象层定义最小可用契约,保证跨平台一致性 - 核心实现提供通用能力(事件、注销、列表) - 扩展方法提升易用性与可组合性 - 平台扩展将生命周期与平台事件对接,实现自动清理 ```mermaid classDiagram class IUnRegister { +UnRegister() void } class DefaultUnRegister { -_mOnUnRegister : Action? +UnRegister() void } class IUnRegisterList { +UnregisterList : IList~IUnRegister~ } class UnRegisterList { -_unRegisterList : IUnRegister[] +Add(unRegister : IUnRegister) void +UnRegisterAll() void } class UnRegisterListExtension { +AddToUnregisterList(self, unRegisterList) void +UnRegisterAll(self) void } class EasyEvent { -_mOnEvent : Action? +Register(onEvent : Action) IUnRegister +UnRegister(onEvent : Action) void +Trigger() void } class EventBus { -_mEvents : EasyEvents +Send~T~() void +Send~T~(e : T) void +Register~T~(onEvent : Action~T~) IUnRegister +UnRegister~T~(onEvent : Action~T~) void } class OrEvent { -_mOnEvent : Action? +UnregisterList : IList~IUnRegister~ +Or(event : IEvent) OrEvent +Register(onEvent : Action) IUnRegister +UnRegister(onEvent : Action) void -Trigger() void } class UnRegisterExtension { +UnRegisterWhenNodeExitTree(unRegister : IUnRegister, node : Node) IUnRegister } IUnRegister <|.. DefaultUnRegister IUnRegisterList <|.. UnRegisterList UnRegisterListExtension ..> IUnRegister : "管理" UnRegisterListExtension ..> IUnRegisterList : "管理" EventBus --> EasyEvents : "使用" EventBus --> EasyEvent : "注册/注销" OrEvent ..|> IUnRegisterList UnRegisterExtension ..> IUnRegister : "绑定" ``` **图表来源** - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) ## 详细组件分析 ### UnRegisterExtension(Godot 平台扩展) - 功能概述:提供扩展方法,将 IUnRegister 与 Godot 节点生命周期绑定,节点退出场景树时自动执行注销 - 关键行为: - 监听节点 TreeExiting 事件 - 在事件触发时调用 IUnRegister.UnRegister() - 返回原始 IUnRegister 实例,支持链式调用 - 使用场景: - UI 页面、场景切换、临时监听器等需要随节点销毁而自动清理的资源 - 调用时机:在注册监听器后立即调用,确保节点生命周期内始终受控 ```mermaid sequenceDiagram participant Node as "Godot 节点" participant Ext as "UnRegisterExtension" participant UR as "IUnRegister" Node->>Ext : "UnRegisterWhenNodeExitTree(UR, Node)" Ext->>Node : "订阅 TreeExiting 事件" Node-->>Ext : "TreeExiting 事件触发" Ext->>UR : "调用 UnRegister()" UR-->>Ext : "完成清理" ``` **图表来源** - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L17-L22) **章节来源** - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) ### DefaultUnRegister(默认注销器) - 功能概述:保存注册的回调,在 UnRegister() 中调用并清理引用,防止重复调用 - 关键行为: - 保存 Action 回调 - 执行回调并置空引用 - 避免重复注销导致的异常 - 使用场景:事件注册返回的 IUnRegister 实例,通常由 EasyEvent/EasyEvents/EasyEventGeneric 等事件系统生成 ```mermaid flowchart TD Start(["进入 UnRegister"]) --> Check["检查回调是否为空"] Check --> |非空| Invoke["调用回调"] Check --> |空| Skip["跳过执行"] Invoke --> Clear["置空回调引用"] Skip --> End(["结束"]) Clear --> End ``` **图表来源** - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L16-L21) **章节来源** - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) ### UnRegisterList 与 UnRegisterListExtension(批量注销) - UnRegisterList:维护 IUnRegister 列表,提供 Add 与 UnRegisterAll - UnRegisterListExtension:扩展方法,将 IUnRegister 添加到 IUnRegisterList,并提供 UnRegisterAll 批量清理 - 关键行为: - AddToUnregisterList:将单个注销项加入列表 - UnRegisterAll:遍历列表逐一调用 UnRegister 并清空集合 - 使用场景:组件或页面集中管理多个监听器、订阅关系、定时器等资源 ```mermaid flowchart TD Start(["开始 UnRegisterAll"]) --> Empty{"列表为空?"} Empty --> |是| End(["结束"]) Empty --> |否| Loop["遍历列表"] Loop --> Call["调用每个 IUnRegister.UnRegister()"] Call --> Clear["清空列表"] Clear --> End ``` **图表来源** - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L29-L36) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L24-L31) **章节来源** - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [UnRegisterListExtension.cs](file://GFramework.Core/extensions/UnRegisterListExtension.cs#L1-L32) - [UnRegisterListExtensionTests.cs](file://GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs#L1-L132) ### EasyEvent 与 EventBus(事件系统) - EasyEvent:无参事件系统,Register 返回 IUnRegister,支持 Trigger 与 UnRegister - EventBus:类型化事件总线,封装 EasyEvents,提供 Send/Register/UnRegister - 关键行为: - Register 返回 IUnRegister,便于后续注销 - EventBus 基于类型管理事件,避免重复创建 - 使用场景:模块间解耦通信、状态变更通知、UI 交互响应等 ```mermaid sequenceDiagram participant Caller as "调用方" participant EBus as "EventBus" participant EAll as "EasyEvents" participant Evt as "EasyEvent" Caller->>EBus : "Register(handler)" EBus->>EAll : "GetOrAddEvent>()" EAll-->>EBus : "返回 Event" EBus->>Evt : "Register(handler)" Evt-->>EBus : "返回 IUnRegister" EBus-->>Caller : "返回 IUnRegister" ``` **图表来源** - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L41-L44) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L74-L84) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L17-L21) **章节来源** - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) ### OrEvent(组合事件) - 功能概述:将多个事件通过“或”逻辑组合,任一事件触发即触发 OrEvent,并维护内部注销列表 - 关键行为: - Or:将其他事件注册到当前 OrEvent,并自动加入注销列表 - UnRegister:取消指定处理函数并触发 UnRegisterAll - 使用场景:多来源触发聚合、条件组合、复杂 UI 交互 **章节来源** - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) ### SignalFluentExtensions(Godot 信号扩展) - 功能概述:为 Godot 对象提供 Signal() 流畅 API,便于与注销机制配合使用 - 使用场景:节点信号订阅与注销的链式调用 **章节来源** - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22) ## 依赖分析 - 抽象接口依赖:IUnRegister 与 IUnRegisterList 是核心契约,被 DefaultUnRegister、UnRegisterList、OrEvent 等实现 - 事件系统依赖:EventBus 依赖 EasyEvents 进行事件实例管理;EasyEvent 依赖 DefaultUnRegister 生成注销令牌 - 平台扩展依赖:UnRegisterExtension 依赖 Godot 节点生命周期事件,实现自动注销 - 扩展方法依赖:UnRegisterListExtension 依赖 IUnRegister 与 IUnRegisterList,提供批量管理能力 ```mermaid graph LR IUR["IUnRegister"] --> DUR["DefaultUnRegister"] IURL["IUnRegisterList"] --> URL["UnRegisterList"] IURL --> OREvt["OrEvent"] EBus["EventBus"] --> EAll["EasyEvents"] EBus --> Evt["EasyEvent"] Evt --> DUR URExt["UnRegisterExtension"] --> IUR SigExt["SignalFluentExtensions"] --> URExt ``` **图表来源** - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22) **章节来源** - [IUnRegister.cs](file://GFramework.Core.Abstractions/events/IUnRegister.cs#L1-L12) - [IUnRegisterList.cs](file://GFramework.Core.Abstractions/events/IUnRegisterList.cs#L1-L14) - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L1-L22) - [UnRegisterList.cs](file://GFramework.Core/events/UnRegisterList.cs#L1-L37) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L1-L57) - [EventBus.cs](file://GFramework.Core/events/EventBus.cs#L1-L55) - [EasyEvents.cs](file://GFramework.Core/events/EasyEvents.cs#L1-L85) - [EasyEvent.cs](file://GFramework.Core/events/EasyEvent.cs#L1-L39) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L1-L23) - [SignalFluentExtensions.cs](file://GFramework.Godot/extensions/signal/SignalFluentExtensions.cs#L1-L22) ## 性能考虑 - 事件注册与注销成本:每次注册返回 IUnRegister,建议在不需要时及时注销,避免回调链过长 - 批量注销:使用 UnRegisterAll 一次性清理,减少循环开销 - 自动清理:通过 UnRegisterWhenNodeExitTree 将清理与节点生命周期绑定,避免手动遗漏 - 内存泄漏防护:DefaultUnRegister 在注销后置空回调,防止闭包持有导致的泄漏 - 平台集成:Godot 信号与节点生命周期结合,确保场景切换时资源自动回收 [本节为通用性能指导,无需特定文件分析] ## 故障排除指南 - 注销多次导致异常:确认 DefaultUnRegister 只会调用一次回调并清理引用 - 批量注销无效:检查 UnRegisterList 是否正确添加 IUnRegister,UnRegisterAll 是否被调用 - 节点退出未清理:确认 UnRegisterWhenNodeExitTree 已在注册监听器后调用 - 组合事件未完全清理:OrEvent 的 UnRegister 会触发 UnRegisterAll,确保内部事件正确注册 **章节来源** - [DefaultUnRegister.cs](file://GFramework.Core/events/DefaultUnRegister.cs#L16-L21) - [UnRegisterListExtensionTests.cs](file://GFramework.Core.Tests/extensions/UnRegisterListExtensionTests.cs#L56-L120) - [UnRegisterExtension.cs](file://GFramework.Godot/extensions/UnRegisterExtension.cs#L17-L22) - [OrEvent.cs](file://GFramework.Core/events/OrEvent.cs#L44-L48) ## 结论 资源管理扩展通过统一的注销接口与平台绑定,实现了事件监听器、订阅关系与节点生命周期的自动化清理,有效降低内存泄漏风险并提升性能稳定性。结合批量注销与组合事件机制,开发者可以更高效地管理复杂场景下的资源生命周期。 [本节为总结性内容,无需特定文件分析] ## 附录 ### 最佳实践清单 - 事件注册后立即获取 IUnRegister,并在合适时机调用 UnRegister 或 UnRegisterAll - 使用 UnRegisterWhenNodeExitTree 将节点相关资源与场景树生命周期绑定 - 通过 UnRegisterList 集中管理组件内的多项注销项,避免遗漏 - 组合事件 OrEvent 适合多来源聚合触发,注意内部事件的正确注册与注销 - 与 SignalFluentExtensions 配合,实现信号订阅的流畅与可维护 ### 调用时机参考 - 事件注册:在组件初始化阶段完成 - 自动清理:在注册监听器后立即调用 UnRegisterWhenNodeExitTree - 批量清理:在组件销毁或页面切换时调用 UnRegisterAll - 组合事件:在 OrEvent 上注册处理函数后,确保内部事件已加入注销列表 [本节为概念性内容,无需特定文件分析]