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();
}