From eae45625a7b0a55f856a37f5a6f96a878d3dc627 Mon Sep 17 00:00:00 2001 From: GwWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:52:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(godot):=20=E9=9B=86=E6=88=90Godot=E7=94=9F?= =?UTF-8?q?=E5=91=BD=E5=91=A8=E6=9C=9F=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增ArchitectureAnchorNode类用于监听场景树销毁事件 - 在AbstractArchitecture中实现AttachToGodotLifecycle方法 - 自动绑定架构销毁逻辑到Godot节点退出时机 - 防止架构组件在热重载或多次初始化时重复挂载 - 完善系统注册与销毁流程,确保资源正确释放 --- .../architecture/AbstractArchitecture.cs | 31 ++++++++++++++++++ .../architecture/ArchitectureAnchorNode.cs | 32 +++++++++++++++++++ GFramework.Core/architecture/Architecture.cs | 8 +++-- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 GFramework.Core.Godot/architecture/ArchitectureAnchorNode.cs diff --git a/GFramework.Core.Godot/architecture/AbstractArchitecture.cs b/GFramework.Core.Godot/architecture/AbstractArchitecture.cs index 49c3b5f..0219ff7 100644 --- a/GFramework.Core.Godot/architecture/AbstractArchitecture.cs +++ b/GFramework.Core.Godot/architecture/AbstractArchitecture.cs @@ -1,4 +1,5 @@ using GFramework.Core.architecture; +using Godot; namespace GFramework.Core.Godot.architecture; @@ -8,6 +9,8 @@ namespace GFramework.Core.Godot.architecture; /// 架构的具体类型,必须继承自Architecture且能被实例化 public abstract class AbstractArchitecture : Architecture where T : Architecture, new() { + private const string ArchitectureName = "__GFrameworkArchitectureAnchor"; + /// /// 初始化架构,按顺序注册模型、系统和工具 /// @@ -16,8 +19,35 @@ public abstract class AbstractArchitecture : Architecture where T : Archit RegisterModels(); RegisterSystems(); RegisterUtilities(); + AttachToGodotLifecycle(); } + + /// + /// 将架构绑定到Godot生命周期中,确保在场景树销毁时能够正确清理资源 + /// 通过创建一个锚节点来监听场景树的销毁事件 + /// + private void AttachToGodotLifecycle() + { + if (Engine.GetMainLoop() is not SceneTree tree) + return; + // 防止重复挂载(热重载 / 多次 Init) + if (tree.Root.GetNodeOrNull(ArchitectureName) != null) + return; + + var anchor = new ArchitectureAnchorNode + { + Name = ArchitectureName + }; + + anchor.Bind(() => + { + Destroy(); + }); + + tree.Root.AddChild(anchor); + } + /// /// 注册工具抽象方法,由子类实现具体的工具注册逻辑 /// @@ -33,3 +63,4 @@ public abstract class AbstractArchitecture : Architecture where T : Archit /// protected abstract void RegisterModels(); } + diff --git a/GFramework.Core.Godot/architecture/ArchitectureAnchorNode.cs b/GFramework.Core.Godot/architecture/ArchitectureAnchorNode.cs new file mode 100644 index 0000000..4770dc7 --- /dev/null +++ b/GFramework.Core.Godot/architecture/ArchitectureAnchorNode.cs @@ -0,0 +1,32 @@ +using Godot; + +namespace GFramework.Core.Godot.architecture; + +/// +/// 架构锚点节点类,用于在Godot场景树中作为架构组件的根节点 +/// 该类提供了退出时的回调绑定功能,可以在节点从场景树中移除时执行清理操作 +/// +public partial class ArchitectureAnchorNode : Node +{ + private Action? _onExit; + + /// + /// 绑定节点退出时的回调动作 + /// + /// 当节点从场景树退出时要执行的动作 + public void Bind(Action onExit) + { + _onExit = onExit; + } + + /// + /// 当节点从场景树中移除时调用此方法 + /// 执行绑定的退出回调并清理引用 + /// + public override void _ExitTree() + { + _onExit?.Invoke(); + _onExit = null; + } +} + diff --git a/GFramework.Core/architecture/Architecture.cs b/GFramework.Core/architecture/Architecture.cs index aebbf70..c1d81c0 100644 --- a/GFramework.Core/architecture/Architecture.cs +++ b/GFramework.Core/architecture/Architecture.cs @@ -65,6 +65,8 @@ public abstract class Architecture : IArchitecture where T : Architecture, /// 存储尚未初始化的系统集合,在初始化阶段统一调用Init方法 /// private readonly HashSet _mSystems = []; + + private readonly HashSet _allSystems = []; /// /// 类型化事件系统,负责事件的发布与订阅管理 @@ -99,7 +101,7 @@ public abstract class Architecture : IArchitecture where T : Architecture, { system.SetArchitecture(this); _mContainer.Register(system); - + _allSystems.Add(system); if (!_mInited) _mSystems.Add(system); else @@ -242,11 +244,11 @@ public abstract class Architecture : IArchitecture where T : Architecture, public void Destroy() { // 销毁所有已注册的系统 - foreach (var system in _mSystems) + foreach (var system in _allSystems) { system.Destroy(); } - _mSystems.Clear(); + _allSystems.Clear(); }