Gamepad stick input triggered too many times

Godot Version

4.2.2

Question

Hi there!
I have a problem with some inputs, more precisely with gamepad sticks.

In my game I mapped (via Input Map) some actions, and some of them need to have a stick up/down. What I want is not a continuous movement, but a discrete one like the press/release of a button.

So I have for example:

And this code (inside a Control node):

func _input(_event: InputEvent) -> void:
	if _event.is_action_pressed("control_up"):
		select_previous()
	
	if _event.is_action_pressed("control_down"):
		select_next()

When I press the stick all the way up or down, it detects a change but if i keep it pressed and tilt the stick just a little it detects an infinite amount of movement, so it continuously triggers one of those two methods in the conditions above.

How can I fix that?
Is there also a best-practice on how to detect input for UI elements and/or game elements (like the player movement)?

Thanks in advance.
I also uploaded a minimal reproduction on github so you can test it directly there.

Try is_action_just_pressed(“”).

Edit: another thing you can do, as I’m doing it more often too, is adding a timer node to configure an “input rate” (similar to like an “attack rate”). That way the input is only polled once every 0.5 seconds or so.

For joysticks it’s detecting little movements that are over the threshold, you may have to add your own debounce variable, or use Control nodes and their “Focus” properties.

var event_rest: bool = true
func _input(event: InputEvent) -> void:
	if event.is_action("control_up"):
		if event.is_pressed() and event_rest:
			event_rest = false
			select_previous()
		elif event.is_released():
			event_rest = true
	
	elif event.is_action_pressed("control_down"):
		if event.is_pressed() and event_rest:
			event_rest = false
			select_next()
		elif event.is_released():
			event_rest = true

I thought about doing a debounce boolean but it seemed to me a bad practice as I was also hoping to implement customization of controls on the player-side (so even buttons like A, B, RB etc… could be mapped to analog sticks).

In this case I should implement that for every action that need a single input in _input callback, am I correct? Or maybe is there an alternative way I don’t see at the moment?

1 Like

is_action_just_pressed is not a method of InputEvent, instead it’s of singleton Input that I’m trying to avoid since I have an event to consume.

The input rate solution could be interesting, I need to evaluate that since I also want to offer the player a total customization of the input commands!