--- title: Godot 项目元数据生成器 description: 说明 project.godot 当前会生成什么、何时生效,以及 AutoLoad 和 Input Action 的映射边界。 --- # Godot 项目元数据生成器 `GodotProjectMetadataGenerator` 读取 `project.godot`,把 Godot 工程级配置转成稳定的编译期入口。 当前只覆盖两类信息: - `[autoload]` 段生成 `GFramework.Godot.Generated.AutoLoads` - `[input]` 段生成 `GFramework.Godot.Generated.InputActions` 它不处理场景节点注入,也不处理节点事件绑定。这两部分分别由 `/zh-CN/source-generators/get-node-generator` 和 `/zh-CN/source-generators/bind-node-signal-generator` 负责。 ## 当前包关系 - 特性来源:`GFramework.Godot.SourceGenerators.Abstractions` - 生成器实现:`GFramework.Godot.SourceGenerators` - 运行时依赖:`GFramework.Godot` - 消费侧生成命名空间:`GFramework.Godot.Generated` ## 最小接入路径 ### NuGet 引用 常规 Godot C# 项目安装 `GeWuYou.GFramework.Godot.SourceGenerators` 后,包内 `targets` 会自动做两件事: 1. 注入 analyzer 2. 如果项目根目录存在 `project.godot`,把它加入 `AdditionalFiles` ```xml ``` ### 仓库内直接引用生成器 如果你通过 `ProjectReference(OutputItemType=Analyzer)` 直接引用生成器项目,需要自己把 `project.godot` 放进 `AdditionalFiles`: ```xml ``` ## 当前会生成什么 ### AutoLoad 入口 假设 `project.godot` 中有: ```ini [autoload] GameServices="*res://autoload/game_services.tscn" AudioBus="*res://autoload/audio_bus.gd" ``` 生成器会产出: ```csharp using GFramework.Godot.Generated; var gameServices = AutoLoads.GameServices; if (AutoLoads.TryGetAudioBus(out var audioBus)) { } ``` 当前输出同时包含: - `AutoLoads.` - `AutoLoads.TryGet(out TNode? value)` 这些访问器最终都通过当前 `SceneTree.Root` 解析 `/root/`。 ### Input Action 常量 假设 `project.godot` 中有: ```ini [input] move_up={ } ui_cancel={ } ``` 生成器会产出: ```csharp using GFramework.Godot.Generated; if (Input.IsActionJustPressed(InputActions.MoveUp)) { } ``` 这部分只生成稳定字符串常量,不会替你封装 `Input` 调用。 ## AutoLoad 类型推断的当前规则 ### 优先级顺序 当前映射顺序是: 1. 显式 `[AutoLoad("Name")]` 2. 按 C# 类型名与 AutoLoad 名称做唯一匹配 3. 无法唯一确定时退化为 `Godot.Node` 例如: ```csharp using GFramework.Godot.SourceGenerators.Abstractions; using Godot; [AutoLoad("GameServices")] public partial class GameServices : Node { } ``` 这类显式映射优先于按类名推断。 ### 什么时候会退化成 `Godot.Node` 以下情况不会中断全部生成,但会把对应入口退化成 `Godot.Node` 并报告诊断: - 多个类型显式映射到同一个 AutoLoad - 不同命名空间下出现同名 `Node` 类型,导致隐式推断不唯一 - 对应条目实际无法唯一绑定到一个 C# 节点类型 ## `project.godot` 文件约束 ### 可以改路径,不能改文件名 NuGet `targets` 支持通过 `GFrameworkGodotProjectFile` 改相对路径: ```xml Config/project.godot ``` 但当前生成器按文件名识别 `project.godot`,所以: - `Config/project.godot` 可以 - `Config/game.project` 不可以 如果文件名不是 `project.godot`,`targets` 会给出 warning,生成器也会忽略该文件。 ### 缺文件或空节时不会生成任何代码 按当前测试,下面几种情况都不会产出源码,也不会报告额外诊断: - 没有把 `project.godot` 传进 `AdditionalFiles` - `project.godot` 是空文件 - `[autoload]` / `[input]` 只有空节,没有有效条目 ## 标识符与重复条目的当前语义 ### 标识符冲突 如果不同名字清洗后落到同一个 C# 标识符,生成器会追加稳定后缀并报告诊断,例如: - `move_up` -> `MoveUp` - `move-up` -> `MoveUp_2` AutoLoad 名称也遵循同样的冲突处理策略。 ### 重复条目 如果同一个 `project.godot` 里重复声明同名 AutoLoad 或 Input Action,当前行为是: - 报告诊断 - 只保留第一条声明参与生成 这和“冲突后同时生成多个重名成员”不是一回事。 ## 与场景级生成器的边界 这项能力解决的是“项目级元数据入口”: - `AutoLoads` - `InputActions` 场景级样板仍然需要其他生成器: - 节点字段注入:`[GetNode]` - 节点 CLR event 订阅:`[BindNodeSignal]` 在 `ai-libs/CoreGrid` 中,这三类能力是并行使用的:`project.godot` 负责 AutoLoad / Input Action,具体 UI 或场景节点再通过 `[GetNode]` 和 `[BindNodeSignal]` 处理。 ## 诊断与约束 当前最值得记住的约束有这些: - `[AutoLoad]` 只能标在继承 `Godot.Node` 的类型上 - 显式或隐式 AutoLoad 映射不唯一时,会退化为 `Godot.Node` - 标识符冲突会追加稳定后缀,而不是覆盖已有成员 - 重复条目只保留第一条声明 ## 推荐阅读 1. [GetNode 生成器](./get-node-generator.md) 2. [BindNodeSignal 生成器](./bind-node-signal-generator.md) 3. [Godot 集成教程](../tutorials/godot-integration.md) 4. [Godot 模块总览](../godot/index.md)