diff --git a/ai-plan/public/documentation-governance-and-refresh/todos/documentation-governance-and-refresh-tracking.md b/ai-plan/public/documentation-governance-and-refresh/todos/documentation-governance-and-refresh-tracking.md index df7f9ff1..3dc3a5e7 100644 --- a/ai-plan/public/documentation-governance-and-refresh/todos/documentation-governance-and-refresh-tracking.md +++ b/ai-plan/public/documentation-governance-and-refresh/todos/documentation-governance-and-refresh-tracking.md @@ -7,19 +7,19 @@ ## 当前恢复点 -- 恢复点编号:`DOCUMENTATION-GOVERNANCE-REFRESH-RP-012` +- 恢复点编号:`DOCUMENTATION-GOVERNANCE-REFRESH-RP-013` - 当前阶段:`Phase 3` - 当前焦点: - 已建立统一公开 skill:`.agents/skills/gframework-doc-refresh/` - 文档重构入口已从“按 guide/tutorial/api 类型拆 skill”收口为“按源码模块驱动文档刷新” - - PR #268 的当前未解决 review 线程已进入收口:Scene/UI 标题层级修正、共享脚本 review 修复、`gframework-pr-review` 多 AI reviewer 支持补齐 - - `Godot.SourceGenerators` 的 4 个高风险专题页已按当前实现重写,下一轮转入 tutorial 收口与 PR thread 收口 + - `docs/zh-CN/tutorials/godot-integration.md` 已按当前实现重写,教程入口不再复刻旧 Godot API 叙述 + - `docs/zh-CN/godot/index.md` 与 `docs/zh-CN/godot/architecture.md` 仍保留同类旧写法,成为下一轮高优先级收口对象 ## 当前状态摘要 - 文档治理规则已收口到仓库规范,README、站点入口与采用链路不再依赖旧文档自证 -- 高优先级模块入口与 `core` 关键专题页已回到可作为默认导航入口的状态,本轮计划中的 `core` 剩余高风险页面已完成收口 -- 当前主题仍是 active topic,因为 `source-generators` 栏目下的 Godot 相关页面仍可能包含与实现漂移的旧内容,且统一 skill 还需要在该场景上继续落地使用 +- 高优先级模块入口、`core` 关键专题页与 `tutorials/godot-integration.md` 已回到“以源码 / 测试 / README 为准”的状态 +- 当前主题仍是 active topic,因为 `docs/zh-CN/godot/` 栏目入口和架构页仍有旧 API / 旧接入路径叙述,Godot 文档链路尚未完全收口 ## 当前活跃事实 @@ -65,6 +65,9 @@ 明确当前不会自动生成 `_Ready()` / `_ExitTree()` - `docs/zh-CN/source-generators/auto-register-exported-collections-generator.md` 已补齐 frontmatter,并改成“成员形状、registry 匹配规则、null-skip 行为、编译期诊断与 CoreGrid 真实采用路径”的结构, 明确生成器依赖的是实例可读集合成员与可读 registry 成员,不要求成员必须带 `[Export]` +- `docs/zh-CN/tutorials/godot-integration.md` 已改成“包关系、`project.godot` 接线、`[GetNode]` / `[BindNodeSignal]` 协作顺序、运行时扩展边界、迁移提醒”的结构, + 不再把 `GetNodeX`、`CreateSignalBuilder`、`AbstractGodotModule` 默认化叙述为当前推荐路径 +- `docs/zh-CN/tutorials/index.md` 中 Godot 教程入口摘要已同步改成“项目级配置 + 生成器协作 + 生命周期边界”,不再继续宣传对象池 / 性能优化式旧范围 - `.agents/skills/gframework-doc-refresh/SKILL.md` 已改成标准 YAML frontmatter skill,并明确支持模块输入、证据顺序、输出优先级与验证步骤 - `.agents/skills/gframework-doc-refresh/SKILL.md` 的 `description` 已加引号,修复 `Recommended command:` 中冒号导致的 invalid YAML skill 加载警告 @@ -85,9 +88,10 @@ `godot-project-generator.md`、`get-node-generator.md`、`bind-node-signal-generator.md` 与 `auto-register-exported-collections-generator.md` 已完成收口; 继续按源码、测试、`*.csproj` 与 `ai-libs/` 下已验证参考实现核对剩余 Godot 相关页面,不把旧文档当事实来源 -- 教程失真回流风险:`docs/zh-CN/tutorials/godot-integration.md` 仍保留旧 API 与旧模块叙述,可能把已清理掉的旧说法重新带回专题页 - - 缓解措施:本轮已确认 `GetNodeX`、`AbstractGodotModule`、`InstallGodotModule` 与 `GFramework.Godot.Pool` 等旧引用仍存在; - 下一轮优先按当前 `GFramework.Godot` / `Godot.SourceGenerators` 实现重写或拆分该教程 +- Godot 栏目入口失真风险:`docs/zh-CN/godot/index.md` 与 `docs/zh-CN/godot/architecture.md` 仍保留 `GetNodeX`、 + `CreateSignalBuilder`、`InstallGodotModule(...).Wait()` 等旧叙述,可能覆盖新教程的采用路径 + - 缓解措施:本轮已完成 tutorial 收口;下一轮优先按当前 `GFramework.Godot` / `GFramework.Godot.SourceGenerators` / + `ai-libs/CoreGrid` 的真实采用路径重写 `godot/index.md`,并评估 `godot/architecture.md` 的最小收口范围 - 采用路径误导风险:根聚合包与模块边界若再次被写错,会继续误导消费者的包选择 - 缓解措施:保持“源码与包关系优先”的证据顺序,改动采用说明时同步核对包依赖与生成器 wiring - 模块映射不全风险:统一 skill 若遗漏模块别名、测试项目或 docs 栏目映射,会让后续扫描阶段直接失焦 @@ -132,10 +136,12 @@ - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/get-node-generator.md` - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/bind-node-signal-generator.md` - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/auto-register-exported-collections-generator.md` +- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/tutorials/godot-integration.md` +- `rg -n "GetNodeX|CreateSignalBuilder|GodotGameArchitecture|AbstractGodotModule|InstallGodotModule\(|GFramework\.Godot\.Pool" docs/zh-CN/godot docs/zh-CN/tutorials -S` - `cd docs && bun run build` ## 下一步 -1. 优先重写或拆分 `docs/zh-CN/tutorials/godot-integration.md`,先移除 `GetNodeX`、`AbstractGodotModule`、`InstallGodotModule` 等旧 API 叙述 -2. 下一次推送后先重新执行 `$gframework-pr-review`,确认 PR #268 的 CodeRabbit / Greptile open thread 是否按预期收敛 -3. 若 tutorial 收口后 active 内容再次变长,把本阶段已完成的 Godot 生成器专题历史迁入 topic `archive/` +1. 优先重写 `docs/zh-CN/godot/index.md`,清掉 `GetNodeX`、`CreateSignalBuilder`、`InstallGodotModule(...)` 默认化叙述 +2. 视 `godot/index.md` 收口结果,决定是否同步压缩 `docs/zh-CN/godot/architecture.md`,避免两页继续互相复制旧接入路径 +3. 下一次推送后重新执行 `$gframework-pr-review`,确认 PR #268 的 CodeRabbit / Greptile open thread 是否按预期收敛 diff --git a/ai-plan/public/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md b/ai-plan/public/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md index 8a3c9c33..300549ca 100644 --- a/ai-plan/public/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md +++ b/ai-plan/public/documentation-governance-and-refresh/traces/documentation-governance-and-refresh-trace.md @@ -2,7 +2,7 @@ ## 2026-04-22 -### 当前恢复点:RP-012 +### 当前恢复点:RP-013 - 本轮从 PR #268 的最新 review 数据恢复,未发现失败检查;CTRF 报告显示 2139 个测试全部通过 - 本轮复核确认当前 PR 的 latest-head open thread 同时来自 `coderabbitai[bot]` 与 `greptile-apps[bot]` @@ -23,8 +23,11 @@ - 新页面统一收口到“包关系、最小接入路径、真实生成语义、生命周期边界、诊断约束”,不再沿用旧教程式长篇 API 罗列 - 本轮额外复核了 `ai-libs/CoreGrid` 的真实采用方式,确认 `[GetNode]` / `[BindNodeSignal]` 组合使用时应先注入节点再绑定事件 - 本轮继续收口 `auto-register-exported-collections-generator.md`,补齐 frontmatter,并把“导出集合”纠正为“实例可读集合成员 + registry 成员 + 单参数实例方法”的真实契约 -- 本轮复核 `docs/zh-CN/tutorials/godot-integration.md`,确认其中仍残留 `GetNodeX`、`AbstractGodotModule`、`InstallGodotModule`、 - `GFramework.Godot.Pool` 等旧 API / 旧模块叙述,tutorial 已成为下一轮高优先级清理对象 +- 本轮已重写 `docs/zh-CN/tutorials/godot-integration.md`,把内容收口为“包关系、`project.godot` 接线、`[GetNode]` / + `[BindNodeSignal]` 协作顺序、运行时扩展边界、迁移提醒”,不再把旧 Godot API 列表当事实来源 +- `docs/zh-CN/tutorials/index.md` 的 Godot 教程入口摘要已同步改成当前采用路径,避免入口页继续把教程描述成对象池 / 性能优化总览 +- 本轮检索确认 Godot 栏目仍有下一批高风险页面:`docs/zh-CN/godot/index.md` 与 `docs/zh-CN/godot/architecture.md` 还保留 + `GetNodeX`、`CreateSignalBuilder`、`InstallGodotModule(...).Wait()` 等旧叙述,应作为 tutorial 之后的下一轮收口对象 ### 当前决策 @@ -35,7 +38,8 @@ - `Godot.SourceGenerators` 专题页继续采用“源码 / 测试 / README 优先,`ai-libs/` 只补消费者 wiring”的证据顺序 - `BindNodeSignal` 页面明确记录“当前不自动生成 `_Ready()` / `_ExitTree()`”,避免继续把它写成自动生命周期织入器 - `auto-register-exported-collections` 页面明确区分“运行时 null 时跳过注册”和“配置错误时编译期报错”,避免旧文档把两类边界混为一谈 -- `godot-integration.md` 不再适合作为当前 Godot 采用路径的事实来源;后续只能把它当待修输出,而不是事实输入 +- `godot-integration.md` 已重新成为可用的采用路径入口;后续 Godot 文档收口应优先处理 `godot/index.md` 和 `godot/architecture.md` +- `docs/zh-CN/godot/index.md` 若继续保留旧写法,会重新把 tutorial 已清掉的旧接入路径带回导航入口,因此优先级高于继续扩展新教程 ### 验证 @@ -51,10 +55,12 @@ - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/bind-node-signal-generator.md` - `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/source-generators/auto-register-exported-collections-generator.md` - `cd docs && bun run build` -- `rg -n "GetNodeX|AbstractGodotModule|InstallGodotModule|GodotGameArchitecture|GFramework\\.Godot\\.Pool" docs/zh-CN/tutorials/godot-integration.md` +- `bash .agents/skills/gframework-doc-refresh/scripts/validate-all.sh docs/zh-CN/tutorials/godot-integration.md` +- `cd docs && bun run build` +- `rg -n "GetNodeX|CreateSignalBuilder|GodotGameArchitecture|AbstractGodotModule|InstallGodotModule\(|GFramework\\.Godot\\.Pool" docs/zh-CN/godot docs/zh-CN/tutorials -S` ### 下一步 -1. 下一次推送后重新执行 `$gframework-pr-review`,确认 PR #268 的 CodeRabbit / Greptile open thread 是否关闭或减少 -2. 继续使用 `gframework-doc-refresh` 对 `Godot.SourceGenerators` 做真实模块扫描 -3. 优先重写或拆分 `tutorials/godot-integration.md`,先清掉已确认失真的 Godot 旧 API 与旧模块示例 +1. 优先重写 `docs/zh-CN/godot/index.md`,清掉 `GetNodeX`、`CreateSignalBuilder`、`InstallGodotModule(...)` 默认化叙述 +2. 视 `godot/index.md` 收口结果,决定是否同步压缩 `docs/zh-CN/godot/architecture.md` +3. 下一次推送后重新执行 `$gframework-pr-review`,确认 PR #268 的 CodeRabbit / Greptile open thread 是否关闭或减少 diff --git a/docs/zh-CN/tutorials/godot-integration.md b/docs/zh-CN/tutorials/godot-integration.md index 94f1d51c..595a5a31 100644 --- a/docs/zh-CN/tutorials/godot-integration.md +++ b/docs/zh-CN/tutorials/godot-integration.md @@ -1,1357 +1,275 @@ +--- +title: Godot 集成教程 +description: 以当前源码和真实消费者接线为准,说明 GFramework 在 Godot 项目中的最小接入路径、生成器协作顺序与常见迁移边界。 +--- + # Godot 集成教程 -> 深入学习如何将 GFramework 与 Godot 引擎完美集成,创建高性能的游戏应用。 +这篇教程只讲当前仓库里仍然成立的 Godot 接入路径: -## 📋 目录 +- 项目级配置:`project.godot` -> `AutoLoads` / `InputActions` +- 场景级样板:`[GetNode]` / `[BindNodeSignal]` +- 运行时辅助:节点生命周期、事件解绑、异步等待 -- [Godot 特定功能](#godot-特定功能) -- [节点生命周期管理](#节点生命周期管理) -- [信号系统集成](#信号系统集成) -- [资源管理优化](#资源管理优化) -- [性能优化技巧](#性能优化技巧) -- [常见集成模式](#常见集成模式) -- [调试与测试](#调试与测试) +它不再把旧版长篇 API 列表当事实来源,也不把 `AbstractGodotModule` / `InstallGodotModule(...)` 当成默认接入起点。 -## Godot 特定功能 +## 先认清包关系 -### 0. project.godot 编译期接入 +一个常见的 Godot + GFramework 项目,通常会同时用到这几层: -如果项目引用了 `GFramework.Godot.SourceGenerators`,现在可以直接把 `project.godot` 中的 AutoLoad 与 Input Action 暴露为强类型 -API: +- `GeWuYou.GFramework`:聚合包,提供 Core / Game 常用能力 +- `GeWuYou.GFramework.Godot`:Godot 运行时扩展,例如节点生命周期辅助、`UnRegisterWhenNodeExitTree`、`WaitUntilReadyAsync` +- `GeWuYou.GFramework.Core.SourceGenerators`:`[ContextAware]`、`[GetSystem]`、`[GetModel]` 等 Core 侧生成器 +- `GeWuYou.GFramework.Godot.SourceGenerators`:`[GetNode]`、`[BindNodeSignal]`、`project.godot` 元数据生成器 + +如果你只装运行时包,没有装生成器包,那么 `[GetNode]`、`[BindNodeSignal]`、`AutoLoads`、`InputActions` 都不会出现。 + +## 第一步:接好项目级配置 + +### 安装包 + +```bash +dotnet add package GeWuYou.GFramework +dotnet add package GeWuYou.GFramework.Godot +dotnet add package GeWuYou.GFramework.Core.SourceGenerators +dotnet add package GeWuYou.GFramework.Godot.SourceGenerators +``` + +`GeWuYou.GFramework.Godot.SourceGenerators` 作为 NuGet 包使用时,会自动把项目根目录下的 `project.godot` 加入 +`AdditionalFiles`。 + +### 什么时候需要手动加 `AdditionalFiles` + +只有在仓库内直接用 analyzer 方式引用生成器项目时,才需要手动补: + +```xml + + + + +``` + +### 可以改路径,不能改文件名 + +如果你的 `project.godot` 不在项目根目录,可以改相对路径: + +```xml + + Config/project.godot + +``` + +但文件名仍然必须是 `project.godot`。当前 `targets` 和生成器都会按这个文件名识别输入。 + +## 第二步:把架构和 Godot 节点分开看 + +当前真实消费者 `ai-libs/CoreGrid` 的默认接入方式,是: + +- 架构层继续用常规 `InstallModule(new SomeModule())` +- Godot 节点脚本通过运行时扩展和源码生成器接入场景 + +也就是说,Godot 集成的主体并不是“所有东西都塞进 Godot 模块”,而是“架构注册”和“场景节点接线”各自负责自己的边界。 + +一个最小架构可以长这样: + +```csharp +using GFramework.Core.Abstractions.Architectures; +using GFramework.Core.Abstractions.Environment; +using GFramework.Godot.Architectures; + +namespace MyGame.Scripts.Core; + +public sealed class GameArchitecture( + IArchitectureConfiguration configuration, + IEnvironment environment) + : AbstractArchitecture(configuration, environment) +{ + protected override void InstallModules() + { + InstallModule(new UtilityModule()); + InstallModule(new ModelModule()); + InstallModule(new GameplayModule()); + InstallModule(new SystemModule()); + } +} +``` + +这里选择 `AbstractArchitecture`,是为了让架构生命周期能挂到 Godot 场景树;但模块注册本身仍然是普通的 +`InstallModule(...)`。 + +## 第三步:把 `project.godot` 变成强类型入口 + +`GFramework.Godot.SourceGenerators` 会读取 `project.godot` 的两个段: + +- `[autoload]` -> `GFramework.Godot.Generated.AutoLoads` +- `[input]` -> `GFramework.Godot.Generated.InputActions` + +例如: + +```ini +[autoload] +GameServices="*res://autoload/game_services.tscn" + +[input] +ui_cancel={ +} +move_up={ +} +``` + +就可以在 C# 里直接使用: ```csharp using GFramework.Godot.Generated; +using Godot; -var services = AutoLoads.GameServices; +if (AutoLoads.TryGetGameServices(out var gameServices)) +{ +} -if (Input.IsActionPressed(InputActions.MoveUp)) +if (Input.IsActionJustPressed(InputActions.UiCancel)) { } ``` -这项能力适合和 `[GetNode]`、`[BindNodeSignal]` 一起使用:前者解决项目级配置入口,后两者解决场景级节点和事件样板。 +这部分只解决“项目级配置入口”,不会处理场景里的节点查找或事件绑定。 -详细说明见:[Godot 项目元数据生成器](../source-generators/godot-project-generator) +## 第四步:把场景节点样板交给生成器 -### 1. 节点生命周期绑定 - -GFramework.Godot 提供了与 Godot 节点生命周期的无缝集成,确保框架初始化与 Godot 场景树同步。 +当前最稳定的场景级接入方式,是让 `[GetNode]` 负责节点字段注入,让 `[BindNodeSignal]` 负责 CLR event 订阅。 ```csharp -using GFramework.Godot.Architecture; +using GFramework.Godot.SourceGenerators.Abstractions; +using Godot; -public class GodotGameArchitecture : AbstractArchitecture +namespace MyGame.Scripts.Ui; + +public partial class MainMenu : Control { - protected override void Init() - { - // 注册核心组件 - RegisterModel(new PlayerModel()); - RegisterSystem(new PlayerControllerSystem()); - RegisterUtility(new AudioUtility()); - } - - protected override void InstallModules() - { - // 安装 Godot 特定模块 - InstallGodotModule(new AudioModule()); - InstallGodotModule(new InputModule()); - } -} -``` + [GetNode] + private Button _startButton = null!; -### 2. Godot 模块系统 + [GetNode] + private Button _quitButton = null!; -创建与 Godot 节点深度集成的模块: - -```csharp -[ContextAware] -[Log] -public partial class AudioModule : AbstractGodotModule -{ - private AudioStreamPlayer _musicPlayer; - private AudioStreamPlayer _sfxPlayer; - - // 模块节点本身 - public override Node Node => this; - - public override void Install(IArchitecture architecture) - { - // 注册音频系统 - architecture.RegisterSystem(new AudioSystem()); - architecture.RegisterUtility(new AudioUtility()); - } - - public override void OnAttach(Architecture architecture) - { - // 模块附加时的初始化 - Logger.Info("Audio module attached"); - - // 创建音频播放器 - CreateAudioPlayers(); - } - - public override void OnDetach(Architecture architecture) - { - // 模块分离时的清理 - Logger.Info("Audio module detached"); - CleanupAudioPlayers(); - } - - public override void OnPhase(ArchitecturePhase phase, IArchitecture architecture) - { - switch (phase) - { - case ArchitecturePhase.Ready: - // 架构准备就绪,开始播放背景音乐 - PlayBackgroundMusic(); - break; - } - } - - private void CreateAudioPlayers() - { - _musicPlayer = new AudioStreamPlayer(); - AddChild(_musicPlayer); - - _sfxPlayer = new AudioStreamPlayer(); - AddChild(_sfxPlayer); - } - - private void CleanupAudioPlayers() - { - _musicPlayer?.QueueFree(); - _sfxPlayer?.QueueFree(); - } - - private void PlayBackgroundMusic() - { - var music = GD.Load("res://assets/audio/background.ogg"); - _musicPlayer.Stream = music; - _musicPlayer.Play(); - } -} -``` - -### 3. 节点池化系统 - -实现高效的 Godot 节点池化,避免频繁的创建和销毁: - -```csharp -using GFramework.Godot.Pool; - -public class BulletPoolSystem : AbstractNodePoolSystem -{ - private Dictionary _scenes = new(); - - public BulletPoolSystem() - { - // 预加载场景 - _scenes["player"] = GD.Load("res://assets/scenes/PlayerBullet.tscn"); - _scenes["enemy"] = GD.Load("res://assets/scenes/EnemyBullet.tscn"); - } - - protected override Bullet CreateItem(string key) - { - if (_scenes.TryGetValue(key, out var scene)) - { - return scene.Instantiate(); - } - - throw new ArgumentException($"Unknown bullet type: {key}"); - } - - protected override void OnSpawn(Bullet item, string key) - { - // 重置子弹状态 - item.Reset(); - item.Position = Vector2.Zero; - item.Visible = true; - item.SetCollisionLayerValue(1, true); - item.SetCollisionMaskValue(1, true); - } - - protected override void OnDespawn(Bullet item) - { - // 隐藏子弹 - item.Visible = false; - item.SetCollisionLayerValue(1, false); - item.SetCollisionMaskValue(1, false); - - // 移除父节点 - item.GetParent()?.RemoveChild(item); - } - - protected override bool CanDespawn(Bullet item) - { - // 只有不在使用中的子弹才能回收 - return !item.IsActive && item.GetParent() != null; - } -} -``` - -## 节点生命周期管理 - -### 1. 自动生命周期绑定 - -使用 GFramework 的扩展方法自动管理节点生命周期: - -```csharp -[ContextAware] -[Log] -public partial class PlayerController : CharacterBody2D, IController -{ - private PlayerModel _playerModel; - public override void _Ready() { - // 设置上下文 - _playerModel = this.GetModel(); - - // 注册事件监听,自动与节点生命周期绑定 - this.RegisterEvent(OnPlayerInput) - .UnRegisterWhenNodeExitTree(this); - - // 监听属性变化,自动清理 - _playerModel.Health.Register(OnHealthChanged) - .UnRegisterWhenNodeExitTree(this); - - // 连接 Godot 信号,自动清理 - this.CreateSignalBuilder(AnimationPlayer.SignalName.AnimationFinished) - .Connect(OnAnimationFinished) - .UnRegisterWhenNodeExitTree(this); + __InjectGetNodes_Generated(); + __BindNodeSignals_Generated(); } - - private void OnPlayerInput(PlayerInputEvent e) - { - // 处理玩家输入 - ProcessInput(e); - } - - private void OnHealthChanged(int newHealth) - { - // 更新 UI 显示 - UpdateHealthDisplay(newHealth); - - // 播放受伤动画 - if (newHealth < _playerModel.PreviousHealth) - { - AnimationPlayer.Play("hurt"); - } - } - - private void OnAnimationFinished(StringName animName) - { - if (animName == "hurt") - { - AnimationPlayer.Play("idle"); - } - } -} -``` -### 2. 延迟初始化模式 - -对于需要在特定时机初始化的组件: - -```csharp -[ContextAware] -[Log] -public partial class AdvancedController : Node, IController -{ - private bool _initialized = false; - - public override void _Ready() - { - // 不立即初始化,等待特定条件 - this.WaitUntil(() => IsInitializationReady()) - .Then(InitializeController); - } - - private bool IsInitializationReady() - { - // 检查所有依赖是否准备就绪 - return HasRequiredComponents() && Context.HasModel(); - } - - private void InitializeController() - { - if (_initialized) return; - - Logger.Info("Initializing advanced controller"); - - // 执行初始化逻辑 - SetupComponents(); - RegisterEventListeners(); - StartUpdateLoop(); - - _initialized = true; - } - - private void SetupComponents() - { - // 设置组件 - } - - private void RegisterEventListeners() - { - // 注册事件监听器 - this.RegisterEvent(OnGameStateChanged) - .UnRegisterWhenNodeExitTree(this); - } - - private void StartUpdateLoop() - { - // 启动更新循环 - SetProcess(true); - } -} -``` - -### 3. 安全的节点操作 - -使用 GFramework 提供的安全扩展方法: - -```csharp -public partial class SafeNodeOperations : Node -{ - public void SafeOperations() - { - // 安全获取子节点 - var player = GetNodeX("Player"); - var ui = FindChildX("UI"); - - // 安全添加子节点 - var bullet = bulletScene.Instantiate(); - AddChildX(bullet); - - // 安全的异步操作 - this.WaitUntilReadyAsync() - .Then(() => { - // 节点准备就绪后的操作 - InitializeAfterReady(); - }); - - // 安全的场景树遍历 - this.ForEachChild(child => { - if (child is Sprite2D sprite) - { - ProcessSprite(sprite); - } - }); - } - - private void ProcessSprite(Sprite2D sprite) - { - // 处理精灵 - } - - private void InitializeAfterReady() - { - // 初始化逻辑 - } -} -``` - -## 信号系统集成 - -### 1. SignalBuilder 流畅 API - -使用 GFramework 的 SignalBuilder 进行类型安全的信号连接: - -```csharp -[ContextAware] -[Log] -public partial class SignalController : Node, IController -{ - private Button _button; - private Timer _timer; - private ProgressBar _progressBar; - - public override void _Ready() - { - InitializeComponents(); - SetupSignalConnections(); - } - - private void InitializeComponents() - { - _button = GetNode