Godot单个实例触发信号却触发所有实例处理函数的问题
解决Godot中多个Area2D实例点击触发多次信号的问题
问题描述
主场景动态创建多个次级场景(Secondary,继承自Area2D)实例,每个实例携带专属信息,点击时通过信号将信息传递给主场景。预期点击不同实例时,主场景仅输出对应实例的信息,但实际点击任意一个实例,都会触发两次输出。
次级场景结构:由Sprite2D和Collision2D组成,用于检测鼠标点击。
原Secondary.gd代码:
class_name Secondary extends Area2D @onready var sprite_2d = $Sprite2D signal secondary_clicked(value) var information func _input(event): if event.is_action_pressed("mouse_left_click"): secondary_clicked.emit(information)
原Main.gd代码:
class_name Main extends Node2D func _ready(): var secondary_scene = preload("res://Secondary.tscn") var secondary_instance = secondary_scene.instantiate() add_child(secondary_instance) secondary_instance.information = "1st" secondary_instance.position = Vector2(510, 320) secondary_instance.secondary_clicked.connect(handle_signal) secondary_instance = secondary_scene.instantiate() add_child(secondary_instance) secondary_instance.information = "2nd" secondary_instance.position = Vector2(710, 320) secondary_instance.secondary_clicked.connect(handle_signal) func handle_signal(value): print("The value from the scene: " + value)
问题原因
_input是全局输入处理函数,场景树中所有节点都会收到输入事件。点击鼠标时,所有Secondary实例都会执行_input内的代码,无论点击位置是否在自身碰撞区域内,因此每个实例都会触发一次信号,导致主场景收到两次信号并输出两次内容。
解决方案
方案1:使用Area2D专属的_input_event函数
_input_event仅在输入事件发生在Area2D的碰撞区域内时才会被调用,确保只有被点击的实例触发信号。
修改后的Secondary.gd代码:
class_name Secondary extends Area2D @onready var sprite_2d = $Sprite2D signal secondary_clicked(value) var information func _input_event(viewport, event, shape_idx): if event.is_action_pressed("mouse_left_click"): secondary_clicked.emit(information)
方案2:在_input中添加碰撞检测
如果坚持使用_input,需要在函数内判断鼠标位置是否在当前实例的碰撞形状范围内,只有符合条件时才触发信号。
修改后的Secondary.gd代码:
class_name Secondary extends Area2D @onready var sprite_2d = $Sprite2D signal secondary_clicked(value) var information func _input(event): if event.is_action_pressed("mouse_left_click"): # 将全局鼠标位置转换为当前节点的本地坐标 var local_mouse_pos = to_local(get_global_mouse_position()) # 检查鼠标是否在碰撞形状内 if $CollisionShape2D.shape.has_point(local_mouse_pos): secondary_clicked.emit(information)
验证效果
修改代码后,点击第一个实例会输出The value from the scene: 1st,点击第二个实例输出The value from the scene: 2nd,单次点击仅触发一次输出,符合预期。
内容的提问来源于stack exchange,提问作者Yoav
相关产品推荐
相关产品推荐

