Problem with drag&drop system

Godot Version

4.3

Question

Good afternoon, how are you?
I’m having a problem with my drag and drop system here. Whenever an area is on top of another Area2D, when i click on it, i drag two objects instead of one.

Look:
Drag&Drop Problem

The code I created was this one I’m using to move the heart parts:

heart_parts.gd

extends Node2D

var can_drag:bool
var offset:Vector2

func _on_area_touch2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton:
		if event.is_action("tap") && event.is_pressed():
			offset = get_global_mouse_position() - global_position
			can_drag = true
		elif event.is_action("tap") && event.is_released():
			can_drag = false


func _physics_process(delta: float) -> void:
	if can_drag:
		global_position = get_global_mouse_position() - offset

func _ready() -> void:
	$AreaTouch2D.connect("input_event", _on_area_touch2d_input_event)

Does anyone know how I can drag only the object I’m clicking on and lock all the other objects around it (which in this case are parts of the heart)? Please?

1 Like

The game thinks you are clicking on both objects.

I would use a static variable to track the dragged item, only picking up a object if the static is null. Also try set_physics_process instead of a variable to disabled the function.

static var picked_item: Node2D

func _on_area_touch2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton:
		if picked_item == null && event.is_action("tap") && event.is_pressed():
			offset = get_global_mouse_position() - global_position
			set_physics_process(true)
			picked_item = self
		elif event.is_action("tap") && event.is_released():
			set_physics_process(false)
			picked_item = null


func _physics_process(delta: float) -> void:
	global_position = get_global_mouse_position() - offset
3 Likes

You should have a look at Viewport.physics_object_picking_first_only.
This setting allows you to indicate that only a single node in the viewport should receive the input_event.

1 Like

Thank you so many, I did what you said and it worked! I didn’t even know about the existence of static variables in godot. :sweat_smile:

heart_parts.gd

extends Node2D

static var target_part:Node2D
var can_drag:bool
var offset:Vector2


func _on_area_touch2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton:
		if  event.is_action("tap") && event.is_pressed() && target_part == null:
			offset = get_global_mouse_position() - global_position
			
			target_part = self
			can_drag = true
		elif event.is_action("tap") && event.is_released():
			target_part = null
			can_drag = false

func _physics_process(delta: float) -> void:
	if can_drag:
		global_position = get_global_mouse_position() - offset


func _ready() -> void:
	$AreaTouch2D.connect("input_event", _on_area_touch2d_input_event)

static variables are pretty new! I think 4.2

I figure from the && you may be familiar with static from another language.