gewuyou e18512f043 docs(documentation-governance): 收口 Game 与 Godot 文档措辞
- 更新 Game / Godot 细页的交叉链接与边界描述,移除内部路径、旧文档对比和命令式跳转

- 更新 GFramework.Godot 与配置工具 README 的公开标签,避免暴露测试路径和原始文档路径

- 补充 documentation-full-coverage-governance 的 RP-049 恢复点、验证结果与 origin/main stop-condition 计量
2026-04-29 13:23:26 +08:00

159 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Godot 信号系统
description: 以当前 GFramework.Godot 源码与 CoreGrid 的动态绑定用法为准,说明 Signal(...) fluent API、SignalBuilder 行为与接入边界。
---
# Godot 信号系统
`GFramework.Godot` 当前提供的信号能力很收敛:它不是另一套事件系统,也不是自动生成绑定代码的入口,而是对
`GodotObject.Connect(...)` 的一层 fluent 包装。
当前真正公开的入口只有两个:
- `SignalFluentExtensions.Signal(...)`
- `SignalBuilder`
如果你需要的是场景节点字段注入和静态 signal 自动绑订,请看
`GFramework.Godot.SourceGenerators``[GetNode]``[BindNodeSignal]`,不要把它们和这里的运行时 fluent API 混成同一层。
## 当前公开入口
### `Signal(...)`
`Signal(...)` 是定义在 `GodotObject` 上的扩展方法:
```csharp
public static SignalBuilder Signal(this GodotObject @object, StringName signal)
```
它只做一件事:基于目标对象和 signal 名称创建一个 `SignalBuilder`。这意味着当前 fluent API 不只适用于 `Node`,也适用于
其他 Godot 对象。
### `SignalBuilder`
`SignalBuilder` 的当前行为来自运行时代码本身:
- `WithFlags(GodotObject.ConnectFlags flags)`
- 把 flags 保存到 builder 内部,作为后续 `To(...)` / `ToAndCall(...)` 的默认连接选项
- `To(Callable callable, GodotObject.ConnectFlags? flags = null)`
- 优先使用参数传入的 flags如果没有再回退到之前 `WithFlags(...)` 保存的值
- 最终直接调用 `target.Connect(signal, callable)``target.Connect(signal, callable, (uint)flags)`
- `ToAndCall(Callable callable, GodotObject.ConnectFlags? flags = null, params Variant[] args)`
- 先执行 `To(...)`
- 再立即执行一次 `callable.Call(args)`
- `End()`
- 返回原始 `GodotObject`
- 主要用于在 fluent 语句结束后重新拿回目标对象,而不是增加新的信号语义
可以把它理解成“对原生 `Connect(...)` 做顺手的链式包装”,而不是带订阅管理、自动解绑、诊断系统的高层抽象。
## 最小接入路径
### 1. 动态绑定时直接用 `Signal(...)`
适合这类场景:
- 运行时创建的节点或弹窗
- signal 名称需要按条件选择
- 你就是想保留手写 `Callable` 的控制权
最小示例:
```csharp
using GFramework.Godot.Extensions.Signal;
using Godot;
public partial class SettingsPanel : Control
{
public override void _Ready()
{
var applyButton = GetNode<Button>("%ApplyButton");
applyButton.Signal(Button.SignalName.Pressed)
.To(Callable.From(OnApplyPressed));
}
private void OnApplyPressed()
{
}
}
```
### 2. 需要连接 flags 时,用 `WithFlags(...)`
`SignalBuilder` 不会解释 flags 的业务含义,只是把它们原样传给 Godot。
```csharp
button.Signal(Button.SignalName.Pressed)
.WithFlags(GodotObject.ConnectFlags.OneShot)
.To(Callable.From(OnStartPressed));
```
如果某一次连接想覆盖默认 flags可以直接在 `To(...)` / `ToAndCall(...)` 上传第二个参数。
### 3. 只有在“连接后立即跑一次”时才用 `ToAndCall(...)`
`ToAndCall(...)` 的语义很直接:先连,再立刻调一次 handler。它适合“先补一次当前状态再继续监听变化”的场景。
```csharp
slider.Signal(Range.SignalName.ValueChanged)
.ToAndCall(Callable.From<double>(OnVolumeChanged), args: [(Variant)slider.Value]);
```
这类调用要求 handler 对“初始化时主动调用一次”是安全的;如果你的处理逻辑不是幂等的,继续用 `To(...)` 更稳妥。
### 4. 静态场景绑定优先交给 `[BindNodeSignal]`
从 [源码生成器总览](../source-generators/index.md) 和当前 Godot 接线方式看,静态场景按钮、滑条、菜单项这类固定
节点,更常见的路径仍然是 `[BindNodeSignal]`
```csharp
[BindNodeSignal(nameof(_startButton), nameof(Button.Pressed))]
private void OnStartPressed()
{
}
```
`Signal(...)` 更常出现在这些动态或补充性绑定里:
- 对话框确认 / 取消等运行时实例
- 运行时选出的 signal 名称
- 需要临时追加监听的 dock、panel、overlay
项目侧常见也会这样写:
```csharp
_quitConfirmDialog.Signal("Confirmed")
.To(Callable.From(OnQuitConfirmDialogConfirmed))
.End();
```
## 什么时候用 fluent API什么时候用生成器
-`Signal(...)`
- 动态节点
- 动态 signal 名称
- 想保留手写 `Callable` 和连接 flags
-`[BindNodeSignal]`
- 节点字段和 signal 都是静态已知
- 你已经在用 `[GetNode]`
- 希望把 `_Ready()` 里的重复绑定样板交给生成器
这两条路径是互补关系,不要求按“先 fluent API、后生成器”的顺序迁移。
## 当前边界
- 动态连接的公开入口是 `Signal(...)`
- 这里不会自动生成 `_Ready()` / `_ExitTree()`,这类能力属于 `GFramework.Godot.SourceGenerators`
- `SignalBuilder` 不提供取消订阅 token也不会替你包装 `Disconnect(...)`
- `End()` 只返回原始对象,不会提交额外配置,也不是必须调用的终止步骤
- signal 名称是否合法、callable 签名是否匹配,仍然遵循 Godot 自身运行时规则
- `ToAndCall(...)` 会在完成连接后立刻执行 handler如果 handler 有副作用,需要你自己确认时机
## 继续阅读
- [Godot 运行时集成](./index.md)
- [Godot 扩展方法](./extensions.md)
- [Godot 集成教程](../tutorials/godot-integration.md)
- [BindNodeSignal 生成器](../source-generators/bind-node-signal-generator.md)