Godot Version
4.4.1
Question
The problem is, when user swipes too fast, my methods that are executed in that swiping action can not catch _unhandled_input(event: InputEvent)
call speed. Thus they are executed late and erratic results/behaviours happen. I tried to solve it with a bool
but again, latent calls have too much difference with the previous call.. so erratic behaviour again^^
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventScreenDrag && !handling_drag:
handling_drag = true
#if multi touch, stop it and do nothing
if event.index != 0:
get_viewport().set_input_as_handled()
handling_drag = false
return
# ignore drag if very small: 2px
if GameUtils.is_two_vectors_2px_close(touch_position, event.position):
handling_drag = false
return
touch_position = event.position
get_parent().drag_position = touch_position
if is_dragging:
get_viewport().set_input_as_handled()
handle_dragging_process() <---- This is the method that can not catch up
handling_drag = false
I check the performance and it looked very normal, problem is very fast swipes. Can i queue this method handle_dragging_process()
calls? Is it a good solution? How should i manage this? I am handling this in input method, should i handle it in process?
What are the erratic results? Some thoughts, based on what you’ve said:
-
You may be getting swipes that have a multitouch component, perhaps a brief one; if you’re swiping quickly, it might pick up a second finger momentarily even if the second finger only comes close to the screen, at which point your if event.index != 0
test may kill a perfectly good swipe depending on the order your fingers registered.
-
Touch input is fundamentally an awful hack in a lot of ways; fundamentally in that it’s not a Godot problem, anything that does touch input has to deal with this. We’re used to things like mouse input where there’s a cursor that’s always somewhere and associated with specific button presses (left click, right click…). Touch has none of that; there may be no valid “cursor” position or many. If there’s more than one, all you can do is check how far those positions were from previous positions and try to guess which ones match. There’s no way to tell what finger you used or get any context other than “there was a touch here that is likely to be related to this other probable sequence of touches from previous frames”.
-
Gesture recognizers for things like swipes are built on top of all that, and add their own layer of heuristics and guesswork. Because the underlying system is a wobbly tower of assumptions, the results are mostly fine but have nasty corner cases where they fall apart. Because there’s no way to sense the player’s intent, gestures also can’t be recognized until they’re already in progress, and they can clash with each other. A classic example is tap vs. double tap; unless you don’t mind both firing, you need to delay any tap recognition until you’re sure it isn’t a double tap, which slows down regular tap detection.
-
What does handle_dragging_process()
do that isn’t keeping up?
2 Likes
Thanks for the explanation and good points. Look at two ss below please
I need to “process” every
single cell “interaction” for length and other game rule related stuff.
handle_dragging_process()
handles what i wrote above. I checked in profiler it is super fast, because no_physics, very small arrays and some small math operations etc. If
swipe
is below than certain speed, than everything works fine. But if somehow
current_swiped cell
has
2 or more gap than
previous_processed_cell
then my all logics fall apart. Probably my already written code design is not architectured to handle this (so maybe fault on my part too )
I understood the problems or limitations of touch controls you mentioned. Currently how i am solving this problem is, ignoring if gap is above >=2 and stopping dragging process to notify user. Still it is acceptable i mean, nobody needs to swipe that fast but still it rose problems.
One question to ask yourself here is how fast the swipe is vs. the sampling rate of the touch input. If you have a 1000Hz touch sampler, a 2560 pixel wide screen and someone does a horizontal swipe across the whole screen in 1/3 of a second, that’s averaging a travel of 7.6 pixels (2560 / 333) per update. That’s handily outrunning your two pixel threshold.
Two pixel control is not needed any more because i have already bool called “handling_drag
”. Again thanks, what you said above made me to look at problem from different perspective