InputEventScreenDrag not keeping up when movement is too fast

Godot Version

4.3

Question

I am simply using InputEventScreenDrag to drag a Area2D node around. However, speed seems to be an issue when dragging the node faster. Ideally, I want the node to keep up, but it seems to lag behind and eventually disconnect from the drag.

Code

extends Area2D

var activated = false
# Called when the node enters the scene tree for the first time.
func _ready():
	pass
	
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	pass
	
func _on_input_event(viewport, event, shape_idx):
	if event is InputEventScreenTouch:
		if event.pressed:
			activated = true
		else:
			activated = false
			
	if event is InputEventScreenDrag and activated:
		position = event.position
		

Demo

I am not sure it will work, but try this:

extends Area2D

var activated = false

var target_pos = Vector2.ZERO

# Called when the node enters the scene tree for the first time.
func _ready():
	pass
	
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	if activated: position = lerp(position, target_pos, delta * 10.0)
	
func _on_input_event(viewport, event, shape_idx):
	if event is InputEventScreenTouch:
		if event.pressed:
			activated = true
		else:
			activated = false
			
	if event is InputEventScreenDrag and activated:
		target_pos = event.position

Hey thanks for replying. It still canā€™t keep up with the speed. I have a feeling some workaround with process() would be the way to fix it, but really canā€™t find any resources with faster polling and processing of InputEvent.

Please can you use physical process? Then tell me the result.

Unfortunately no luck when using _physics_process()

I havenā€™t tested the build on my iPad, only testing on my computer. I am hoping that because I am using ā€˜Emulate Touch from Mouseā€™, the emulation is the problem. Maybe simply building the game on my tablet will not have the same issue.

Hi @gavyn-ezell , did you manage to find a solution to this?

I recommend a different approarch using _process callback to move the node:

extends Area2D


# --- Signals --- #
# --- Enums --- #
# --- Constants --- #
# --- Exported Variables --- #
# --- Public Variables --- #
# --- Private Variables --- #
# --- Onready Variables --- #


# --- Engine Callbacks --- #
func _ready() -> void:
	# Turn off the _process to not drag after start
	set_process(false)


func _process(delta: float) -> void:
	# Set the position for the mouse position, using emulate mouse from touch 
	# will make it work on mobile (already turned on by default in project settings)
	global_position = get_global_mouse_position()


func _input(event: InputEvent) -> void:
	if event is InputEventScreenTouch:
		# When the event is a touch being released and _process is on, turn off _process
		if event.pressed == false and is_processing():
			set_process(false)


# --- Public Functions --- #


# --- Private Functions --- #
# - Common Use Functions - #
# - Setget Functions - #


# - Signal Functions - #
func _on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	# When a sceen touch inside the area is detected, turn on _process to start the drag
	if event is InputEventScreenTouch and event.pressed:
		set_process(true)

1 Like

Yeah I made sure to use _input(event) in the main scene code instead of _on_input_event(). This made the tracking a lot better and I could move a test sprite around at a higher speed. Donā€™t really understand it quite well but I can also show what I did if you need.

1 Like

@matheusmdx @gavyn-ezell thanks both for the pointers.

This seems to work as i intended:

EDIT for readers from the future
I did some changes to support both mouse and touch on mobile phone.
Add filter on event index to avoid weird behavior when multi touching.
ā€œEmulate Touch from mouseā€ and ā€œEmulate mouse from touchā€ should be set to true.

extends Node2D

var _dragging: bool = false
func _input(event: InputEvent) -> void:
	if _dragging and event is InputEventScreenDrag:
		var dragEvent: InputEventScreenDrag = event
		if dragEvent.index > 0:
			return
		position += dragEvent.relative
		get_viewport().set_input_as_handled()

func _on_area_2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventScreenTouch:
		var touchEvent: InputEventScreenTouch = event
		if touchEvent.index > 0:
			return
		_dragging = event.pressed