godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.88k stars 20.15k forks source link

Input `is_action_just_pressed()` is sometimes triggered twice on joypad X axis #72737

Open yikescloud opened 1 year ago

yikescloud commented 1 year ago

Godot version

3.5

System information

windows 10

Issue description

When use Input.is_action_just_pressed("ui_left") and joypad is binding to the action, when you move the joystick, this will send twice sometime, it seems only happens when you drag the stick faster, and it only happens on x axis. Seems this error is not cause by controller issue( I test for multiple gamepads. they all happened).

And if you check the message, you will find Input.is_action_just_pressed("ui_left") return true even the event.axis = 1.

Steps to reproduce

Use Input.is_action_just_pressed("ui_left") to get a input binding with joystick.

Minimal reproduction project

DoubleJoystickPress.zip

Calinou commented 1 year ago

I can confirm this on 3.5.1 and 4.0.beta17 (Linux, DualSense wired controller).

Output from the MRP when flicking the stick up, down, left, then right:

PRESS UP============
PRESS DOWN============
PRESS LEFT============
PRESS LEFT============
PRESS RIGHT============
PRESS RIGHT============

This only sporadically occurs, and only for Left/Right. If you remap the actions to be on the other axis, you can notice this issue is related to the gamepad X axis, not the action names (as the issue will occur with "Press up" and "Press down" instead, when moving the stick horizontally).

This issue also occurs when remapping the ui_left and ui_right actions to use the right stick. The issue doesn't seem to occur when using the shoulder triggers (L2/R2), though it may seem to happen if pressing those slowly (due to the axis going over the deadzone for a small period of time due to controller analog imprecision, your hands shaking, etc).

If you modify the demo to disable V-Sync in the Project Settings and display the frame count, you will notice that both events are printed on the same rendered frame (even though we're rendering 1,000+ frames per second):

PRESS RIGHT============ 8679
PRESS RIGHT============ 8679
PRESS LEFT============ 16158
PRESS LEFT============ 16158
Script ```gdscript extends Node func _input(event): if event is InputEventJoypadMotion: if Input.is_action_just_pressed("ui_left"): print("PRESS LEFT============ %d" % Engine.get_idle_frames()) elif Input.is_action_just_pressed("ui_right"): print("PRESS RIGHT============ %d" % Engine.get_idle_frames()) elif Input.is_action_just_pressed("ui_up"): print("PRESS UP============ %d" % Engine.get_idle_frames()) elif Input.is_action_just_pressed("ui_down"): print("PRESS DOWN============ %d" % Engine.get_idle_frames()) ```

An easy fix is likely to only allow considering each action as just_pressed once per rendered frame, not more. Humans generally can't perform more than ~12 axis changes or button presses per second, so this is probably fine.

yikescloud commented 1 year ago

An easy fix is likely to only allow considering each action as just_pressed once per rendered frame, not more. Humans generally can't perform more than ~12 axis changes or button presses per second, so this is probably fine.

My fix is use event.axis to make a double check, it works

Vitorgus commented 1 year ago

I'm having a similar issue, but on a button press instead of a joy axis.

When trying with an action mapped to a button (e.g. ui_accept mapped to Sony X, Microsoft A, etc etc), it has been activating multiple times in the same idle frame, sometimes three or four times.

I've tested it in Godot 3.5.2 and 4.0.3, with a wireless Dualshock 4 in a Windows 11.

Can provide more information if needed, or open a new bug report if necessary.

Minimal reproduction Godot 3: PressAndReleaseTest-Godot3.zip Godot 4: PressAndReleaseTest-Godot4.zip

EligijusK commented 5 months ago

I'm having this issue in Godot 4.2.1 when pressing joy axis and dpad axis. I'm using Dualshock 4 controller and Windows 11, I will check with Xbox controller on monday. But if I recall correctly there is no problem with Xbox controller.