HOME / 第 2 部分 · 核心概念与 GDScript 语法 / 第 9 课
MODULE 2 · 核心概念与 GDScript 语法

第 9 课 · 信号(Signal)与节点通信

⏱ 预计时长 25 分钟📊 难度 入门📚 模块 第 2 部分 · 核心概念与 GDScript 语法

🎯 本课学习目标

游戏里到处都是「A 发生了一件事,B 要知道」。信号(Signal)就是 Godot 的答案。本课讲透信号机制。

📖 详细教学步骤

什么是信号?概念

信号(Signal)是一种广播:一个节点可以「发射」一个信号,其他节点可以「监听」这个信号并做出反应。

  • 例:按钮被点击 → 发射 pressed 信号 → 监听方执行对应逻辑
  • 例:敌人死亡 → 发射 died 信号 → 游戏逻辑加分
  • 这是一种「解耦」设计:发出方不需要知道谁会听

💡 常见内置信号:Button 的 pressed、Timer 的 timeout、Area2D 的 body_entered

用代码连接信号(connect 法)实操

在场景中添加一个 Button 和一个脚本(挂在根节点),然后在 _ready() 里连接:

GDSCRIPTextends Node2D

@onready var btn = $Button   # 获取场景里的按钮

func _ready():
    # 参数1:信号名, 参数2:要调用的函数, 参数3:监听者(默认自身)
    btn.pressed.connect(_on_btn_pressed)

func _on_btn_pressed():
    print("按钮被点击了!")   # 输出到底部面板

用代码连接带参数的信号实操

Timer 的 timeout 不带参数,但很多信号带参数(如 Area2D 的 body_entered 会传入进入的物体):

GDSCRIPTextends Node2D

@onready var area = $Area2D

func _ready():
    # body_entered 会传入一个 body 参数
    area.body_entered.connect(_on_body_entered)

func _on_body_entered(body):
    print("有物体进入区域:", body.name)

在编辑器里可视化连接信号实操

  1. 选中按钮节点
  2. 切换到右侧检查器的「节点」标签页(Node 选项卡)
  3. 看到「信号」列表,双击 pressed
  4. 选择「接收方」节点(比如根节点),点连接
  5. Godot 会自动创建 _on_btn_pressed() 函数并帮你连接好

💡 编辑器连接会自动生成函数名,对新手最友好,推荐先用这种方式。

自己定义信号(进阶预览)进阶

你也可以让敌人节点自定义一个「死亡」信号,让别的节点监听(第 26 课实战会用到):

GDSCRIPT# enemy.gd
signal died   # 自定义信号

func take_damage(amount):
    hp -= amount
    if hp <= 0:
        died.emit()   # 发射信号
        queue_free()  # 删除自己
⚠️
信号连了但函数没执行?

检查:①信号名是否正确;②函数名与参数是否匹配;③接收方节点是否已加入场景树。常见坑是忘记写括号 connect(_on_x) 而不是 connect(_on_x)。

⚠️
连接时报错「无法连接到不存在的信号」?

确认信号名拼写正确,Godot 是大小写敏感的。可用检查器里的信号列表核对。

🧪 动手试一试

🏋️ 课后练习

在场景里放一个 Button 和 Timer,设置 Timer 的 Wait Time 为 1 秒并勾选 Autostart,用代码把 Timer 的 timeout 信号连接到 print 函数,运行观察每 1 秒输出一次。

Timer 属性:Wait Time=1、Autostart=true。代码里 timer.timeout.connect(_on_timeout)。

💡

信号是 Godot 最优雅的通信方式,多练多用,它是后面所有项目的基石。

💡

查看节点所有内置信号:选中节点 → 检查器「节点」标签 → 信号列表。

🎓 本课小结

信号是节点间的广播通信机制:节点发射信号,其他节点监听并响应。编辑器可视化连接 + 代码 connect 两种方式都推荐掌握。