GDScript 入门笔记(十):信号

发布时间:2026/9/7 21:42:23

GDScript 入门笔记(十):信号
在 Godot 里写游戏逻辑迟早会遇到一个情况某个事件发生了其他节点需要知道并做出反应。比如玩家按了按钮门开了敌人死了分数增加了计时器到时间了角色能行动了。这些“发生了什么”的通信Godot 提供了一套专门的机制叫信号signal。信号本质上就是事件的广播系统某个节点发出一个信号其他关心这个信号的节点可以提前连接并收到通知。这篇笔记就聊聊信号怎么用怎么自定义信号以及它在实际项目里的好处。一、为什么需要信号假设你有一个玩家节点当玩家死亡时你要做很多事情播放死亡动画、更新 UI、扣除生命数、显示游戏结束画面。如果不用信号你可能会在玩家脚本里直接去调用其他节点的函数比如func die(): $AnimationPlayer.play(die) $UI.update_score() $GameManager.player_died()这样写玩家脚本就不得不知道动画、UI、游戏管理器这些节点的存在耦合很紧。一旦这些节点改了名字或结构玩家脚本也得跟着改。信号解决了这个问题。玩家只需要在死亡时发射一个信号比如died而关心这个信号的其他节点各自在自己的脚本里连接这个信号并处理玩家根本不需要知道它们是谁。这种模式让代码更容易维护和扩展也是 Godot 官方推荐的做法。二、信号的基本概念信号是 Godot 对象所有继承自Object的类包括节点的一种特殊属性。你可以把信号理解成一个“事件名称”当事件发生时用emit_signal()把它发射出去所有连接到这个信号的函数都会被调用。发射信号由某个对象发起通知“某件事发生了”。连接信号其他对象监听这个信号当信号发射时它们注册的函数就会被执行。一个信号可以连接多个函数同一个函数也可以连接到多个信号。三、使用内置信号Godot 的很多节点自带信号比如按钮的pressed、计时器的timeout、碰撞体的body_entered。这些信号我们不需要定义直接连接就能用。代码连接最常见的方式是在_ready()里用connect()方法连接信号。extends Node2D onready var button $Button func _ready(): button.pressed.connect(_on_button_pressed) func _on_button_pressed(): print(按钮被按下了)button.pressed是按钮节点的信号。.connect(_on_button_pressed)把这个信号连接到_on_button_pressed函数。当按钮被按下pressed信号发射_on_button_pressed就会被调用。连接的方法名没有强制要求但通常以_on_开头表示这是一个信号回调方便阅读。编辑器连接在 Godot 编辑器里你也可以通过“节点”面板的“信号”页签来连接信号。选中节点点击信号旁边的“连接”然后选择目标节点和方法编辑器会自动生成连接代码。这样更直观但代码连接更灵活、可读性更好尤其在动态创建节点时。四、自定义信号除了内置信号你也可以在脚本中定义自己的信号。语法是用signal关键字写在成员变量区域。extends Node2D signal health_changed(new_health) signal died定义信号时可以带参数表示发射信号时会传递的数据。health_changed带一个参数new_health而died不带参数。发射自定义信号用emit_signal()发射信号参数按定义时的顺序传递。func take_damage(amount): health - amount emit_signal(health_changed, health) if health 0: emit_signal(died)第一个参数是信号名字符串后面是信号携带的参数。注意信号名字不要写错否则会报错。为了安全也可以用emit_signal(health_changed, health)但 GDScript 4 支持直接用信号名health_changed.emit(health)更简洁也能避免拼写错误。使用信号名直接发射推荐GDScript 4 中signal定义后可以像调用方法一样使用.emit()发射不需要用字符串health_changed.emit(health) died.emit()这样更安全编辑器也会检查。五、连接自定义信号连接自定义信号和连接内置信号一样用connect()。# 在另一个节点脚本中 onready var player $Player func _ready(): player.health_changed.connect(_on_player_health_changed) player.died.connect(_on_player_died) func _on_player_health_changed(new_health): print(玩家血量变化, new_health) func _on_player_died(): print(玩家死了)连接时回调函数的参数需要和信号定义的参数匹配。如果信号带一个参数回调函数也要有一个参数。六、断开信号如果不再需要接收信号可以用disconnect()断开连接。player.health_changed.disconnect(_on_player_health_changed)通常在节点销毁前如果连接的信号来自其他对象最好手动断开但 Godot 在节点释放时会自动断开相关连接如果是对象间的连接当接收者被释放时自动断开。不过如果你手动管理连接还是显式断开更清晰。七、信号连接的几种写法1. 使用connect()方法这是最标准的方式上面已经演示。2. 使用 lambda 表达式GDScript 4 支持用 lambda 作为回调适合简单逻辑不用单独定义函数。button.pressed.connect(func(): print(按钮被按下) )如果信号带参数lambda 也可以接收player.health_changed.connect(func(new_health): print(血量:, new_health) )3. 使用Callable可以把函数引用存成变量再连接。var callback Callable(self, _on_button_pressed) button.pressed.connect(callback)不过最常用的还是直接方法名。八、信号参数的传递信号可以传递任意数量和类型的参数。定义时写参数名发射时按顺序传入连接时回调函数按顺序接收。signal player_scored(player_name, points) func _ready(): player_scored.emit(Tom, 10) func _on_player_scored(player_name, points): print(player_name, 获得 , points, 分)参数个数必须匹配否则连接时会出错或运行时报错。九、await 与信号GDScript 的await关键字可以暂停函数执行直到某个信号发射。这常用于协程式逻辑比如等待按钮点击再继续。func wait_for_button(): await button.pressed print(按钮终于被按了)这行代码会让函数暂停在await处直到button.pressed信号发射然后继续执行后面的代码。await还可以获取信号参数如果信号带参数func wait_for_health_change(): var new_health await player.health_changed print(血量变化为:, new_health)注意await会挂起整个函数的执行但不会阻塞主线程其他节点的逻辑照常运行。它是实现异步逻辑的好工具。十、信号与代码解耦实例假设我们有一个游戏管理器需要知道玩家死亡和得分事件。不用信号时管理器要引用玩家节点。用信号后玩家只负责发信号管理器连接信号即可。玩家脚本class_name Player extends CharacterBody2D signal died signal score_changed(new_score) var score 0 func add_score(amount): score amount score_changed.emit(score) func die(): died.emit() queue_free()游戏管理器脚本extends Node onready var player $Player func _ready(): player.died.connect(_on_player_died) player.score_changed.connect(_on_score_changed) func _on_player_died(): print(游戏结束) func _on_score_changed(new_score): print(当前分数, new_score)这样玩家脚本完全不知道管理器的存在管理器只依赖玩家的信号。当玩家死亡管理器自动收到通知耦合度大大降低。十一、信号使用中的注意事项发射信号时必须确保有连接吗不需要。如果没人连接发射信号不会做任何事也不会报错。信号发射是同步的所有连接的回调会立即执行执行完毕后emit_signal()才返回。所以不要在回调里做可能无限递归的事情。连接要避免重复如果同一个信号连接了同一个函数两次信号发射时函数会被调用两次。需要小心尤其是在动态连接时可能无意识重复连接。可以在连接前先检查is_connected()。回调函数不要依赖顺序多个回调的执行顺序不保证不要依赖。信号名命名习惯用过去式或事件名比如died、health_changed、item_picked_up。十二、总结信号是 Godot 中最重要的通信机制它让节点之间解耦代码更清晰。这篇笔记涵盖了信号的概念和为什么使用信号使用内置信号自定义信号及发射连接和断开信号信号参数的传递await与信号的结合实际解耦示例掌握信号后你会发现写游戏逻辑时少了很多“找节点”的烦恼。

相关新闻

TVA具身智能“原生大脑”:TVA具身意识流架构揭秘

TVA具身智能“原生大脑”:TVA具身意识流架构揭秘

2026/9/7 21:32:23

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”或“TVA视觉智能体”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积…

TVA具身智能“原生大脑”:TVA具身主体性架构新范式

TVA具身智能“原生大脑”:TVA具身主体性架构新范式

2026/9/7 21:32:23

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”或“TVA视觉智能体”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积…

TVA具身智能“原生大脑”:具身智能的整全性架构解析

TVA具身智能“原生大脑”:具身智能的整全性架构解析

2026/9/7 21:32:23

前沿技术探索:TVA智能体(简称TVA)TVA智能体(亦称“AI智能体视觉”或“TVA视觉智能体”)是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习(DRL)、卷积…

组态王与三菱PLC OPC通讯联机仿真调试全解析

组态王与三菱PLC OPC通讯联机仿真调试全解析

2026/9/8 0:42:32

电镀车间的工程师群里,隔三差五就有人发一问:上位机用的组态王6.55,底下是三菱PLC,数据死活上不来,有没有人能讲讲这中间到底走的什么路?这个问题我太熟了。前几年做电镀线改造,我也是从"仿…

金融数据分析中的停复牌事件建模与实战策略

金融数据分析中的停复牌事件建模与实战策略

2026/9/8 0:42:32

1. 项目背景与核心价值 在金融数据分析领域,停复牌事件一直是影响投资决策的关键因素。以"jmg"为例(注:此处为示例代码,实际分析需替换为具体标的),其停复牌历史往往隐藏着市场情绪、资金流向和机…

鲸鱼算法优化XGBoost参数实战:金融风控案例解析

鲸鱼算法优化XGBoost参数实战:金融风控案例解析

2026/9/8 0:42:32

1. 项目概述:当鲸鱼算法遇上XGBoost去年在金融风控项目里,我遇到了一个棘手的问题:传统XGBoost模型对用户还款行为的预测准确率始终卡在87%的瓶颈。直到尝试将鲸鱼优化算法(WOA)引入超参数调优过程,最终将AUC提升到92.3%。这次经历…

FTIR工业废气监测技术:智能动态稀释与光谱解析创新

FTIR工业废气监测技术:智能动态稀释与光谱解析创新

2026/9/8 0:42:32

1. 项目背景与核心价值在工业废气监测领域,传统FTIR(傅里叶变换红外光谱)技术长期面临两大痛点:高浓度气体测量时的信号饱和问题,以及复杂多组分气体交叉干扰的识别难题。我们团队研发的FTX-ONE-CL系统通过独创的稀释采…

电动移行机从设计到调试:重载搬运平车选型与故障排查指南

电动移行机从设计到调试:重载搬运平车选型与故障排查指南

2026/9/8 0:42:32

做非标设备这些年,电动移行机我接触得不算少。很多车间的第一台电动平车,都是因为行车忙不过来、叉车拐不过弯、人工推料车推到腰肌劳损之后才咬牙上的。这东西名字听着专业,但原理一点不玄乎:就是一台能在车间里沿着轨道或地面跑…

幽默笑话集锦的内容筛选与运营策略

幽默笑话集锦的内容筛选与运营策略

2026/9/8 0:32:32

1. 项目概述:幽默笑话集锦的日常价值"每日一笑"这类内容之所以能长期存在并广受欢迎,关键在于它满足了现代人三个核心需求:一是高压生活下的情绪调节阀,二是社交场景中的破冰利器,三是碎片化时间的轻量级消遣…

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/7 20:21:46

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/7 3:44:24

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/7 8:03:37

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

芯片良率波动可视化:动画拆解工艺因果,重建客户信任

芯片良率波动可视化:动画拆解工艺因果,重建客户信任

2026/9/8 0:02:30

芯片这个行业有个不太被人摆到台面上、但几乎每天都在发生的场景:客户拿着一条良率曲线截图问你,这批货的良率怎么掉了三个点,是不是工艺出问题了,产生的不良会不会流到他们产线上去。你解释了半天,客户似懂非懂&#…

PyTorch DataLoader参数冲突:sampler与shuffle互斥的根源与正确写法

PyTorch DataLoader参数冲突:sampler与shuffle互斥的根源与正确写法

2026/9/8 0:02:30

ValueError: sampler option is mutually exclusive with shuffle,这个报错我在 PyTorch 的 DataLoader 上至少见过几十次了,而且很有意思的是,它经常不是新手专属——很多写了好几年模型的老手,在从单机改成自定义采样器&#xf…

中国车企再破谣言,GAC吉利零跑获欧盟安全五星

中国车企再破谣言,GAC吉利零跑获欧盟安全五星

2026/9/8 0:02:30

有人可能在网上开着皮卡拍视频,声称中国电动车不仅性能不如美国大排量车型,安全性也堪忧。然而事实恰恰相反,GAC、吉利和零跑最新推出的电动车型在极为严苛的欧盟新车安全评鉴(Euro NCAP)测试中全部斩获满分。就在特斯…

远程协作的工作台整理

远程协作的工作台整理

2026/9/7 3:38:07

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/4 7:42:10

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/6 23:21:51

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…