学习空间/信号:让对象通知,而不是接管
Godot 核心 / LESSON 08

信号:让对象通知,而不是接管

按钮只报告“被按下”,由接收者决定接下来发生什么。

基础约 7 分钟阅读,实作另计7 节现在学
CONCEPT MAP先看一眼知识之间的联系
先看一眼知识之间的联系01玩家按下02发出事实03传递参数04听众更新
在通知链的边界观察来源、次数与参数,可以区分没收到、接错对象和重复响应。

01直接调用与信号的区别

直接调用适合“我明确要求你做某件事”;信号适合“我发生了一件事,关心它的对象可以响应”。一个调查物件可以发出 inspected,UI 显示文字,房间流程记录一次调查。物件本身不必知道所有接收者的节点路径。信号不是后台线程,也不会自动保存状态。

02交互图解:发出与接收

点击按钮观察计数和日志。这个模拟器用网页脚本解释信息流,没有执行 GDScript。真正的项目里还要保证连接存在、签名匹配,并防止重复连接。

03最小可运行练习

signal_practice.gd gdscript
extends Control

@onready var test_button: Button = $TestButton
@onready var result_label: Label = $ResultLabel
var press_count: int = 0

func _ready() -> void:
    test_button.pressed.connect(_on_test_pressed)
    result_label.text = "还没有按下"

func _on_test_pressed() -> void:
    press_count += 1
    result_label.text = "已按下 %d 次" % press_count
  1. 建立 Control 根节点,添加名为 TestButton 的 Button 和 ResultLabel 的 Label。
  2. 分别设置位置,避免按钮与标签重叠;给按钮填写文字。
  3. 把脚本挂在根节点,只用代码连接,不再在编辑器重复连接同一回调。
  4. F6 后按三次按钮,确认计数恰好加三。

04如何排查“按了没有反应”

先确认按钮实际接收到输入,再检查信号是否连接,随后在回调中打断点。若一个点击加了两次,查重复连接或多份 UI 实例。若回调已经进入但画面没变,检查你更新的是不是屏幕上那一个 Label。把整条链分段检查,比整份重写快。

05给一条通知找两个不同的听众

沿用按钮计数实验,再添加一个 Label 显示最近操作说明。点击同一个按钮后,一个回调更新次数,另一个回调更新文字。先画两条箭头,再写连接代码:按钮发出 pressed,计数显示和操作说明分别接收。这样做的重点不是让一个按钮拥有更多效果,而是看见发出方并不需要亲自操作所有界面。

接着暂时移除第二条连接,观察次数是否仍然增加。能够独立去掉一个听众,而不修改按钮本身,是通知式协作的直观收益。不要把这解释成“任何调用都要改成信号”;若一个对象明确要求另一个对象打开面板,直接调用含义清楚的方法也可能更合适。选择依据是双方的关系,不是信号听起来更高级。

06参数应该携带事实,不让听众再猜一次

如果以后有多个可调查物件,仅发送“有人调查了”可能不够。接收者需要知道是哪一个物件,才能显示正确说明。设计信号时先写一个自然语言句子:“物件发生调查,携带稳定标识和需要展示的内容。”再决定参数的名称与类型。不要为了省一个参数,让每个接收者重新扫描整个房间寻找“刚刚变化的东西”。

同时注意参数不等于永久所有权。把一个场景节点传给长寿命对象后,该节点仍可能随切换释放。如果接收方只需要一段文字或标识,就传所需数据;确实需要节点行为时才传节点引用。练习时让两个按钮发送不同标签,接收端打印标签,确认每次来源明确。把打印文本和画面标签对应起来,比只看“回调进来了”更容易发现串线。

07把没有反应和反应两次分开排查

没有反应时,按“输入到达—信号发出—回调进入—界面更新”四段检查,在每个边界只放一条临时日志。若前两段通过,就不要继续改按键绑定;若回调已经执行,重点检查被修改的 Label 是否是当前可见实例。反应两次则先数场景里有几份按钮或面板,再检查编辑器连接与代码连接是否重复,以及重开面板时有没有重新连接。

一个实用的验收是:启动后点击三次,关闭面板再打开,再点击一次,总数只能增加四。随后移除一个听众,其余听众仍按预期响应。记录连接发生的位置和发生次数,结束实验后清理临时日志。不要为了压住重复响应添加一个随意的延迟;若根因是重复连接,延迟只会把同一个问题藏得更难观察。

动手后,再勾选

不是“我看懂了”,而是你在独立练习里做出并检查过。

CHECK YOUR UNDERSTANDING

换一个情景,你会怎么判断?

信号最合适表达哪种语义?

用自己的话,留一条笔记

可以写“我之前以为……,现在发现……”,或者记录还没解决的问题。

仅保存在此浏览器0 / 20000

回到资料核对

本课是解释与练习,不替代对应版本的官方手册。网页实验不运行 Godot;未标明实机验证的代码,仍需在独立工程中检查。

把这课收进你的理解里。

标记已读不会自动勾选实作,也不代表游戏功能已经完成。

输入一个你想弄明白的问题。

按 Esc 关闭 · 标题、关键词和正文一起搜索