You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 04:56:28