godotengine / godot

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

My gamepad d-pad is executing is_action_just_pressed twice #45443

Open fagnerln opened 3 years ago

fagnerln commented 3 years ago

Godot version: 3.2.3.stable

OS/device including version: OpenSUSE Tumbleweed 20210120 kernel Linux 5.10.7-1

Issue description: When I use the gamepad to control the sprite, it executes the function two times, on the keyboard and mouse button works well.

I found a similar issue here: https://github.com/godotengine/godot/issues/43492 but it's related to mouse, and my mouse is working, so maybe it's a different bug. I even set Input.set_use_accumulated_input(false) as one comment suggests, it don't work.

I created a video showing what happens: https://www.youtube.com/watch?v=WuNF8gArbb8

Notice that the output prints the message twice when I use the gamepad

After that I discovered one more thing, it only happens on the D-Pad, I set to the analog and works correctly, and I set to the face buttons: up to Y, down to A, left to X and right to B and works well, so maybe it's a really specific bug to how it works with the D-Pad

Steps to reproduce: 1 - Open and run the project 2 - Start moving the player with the d-pad of gamepad

Minimal reproduction project: TesteInput2.zip

It's a simple code if don't want to import the project, just put a sprite on the scene:

const TILE_SIZE = 64

func _ready():
    Input.set_use_accumulated_input(false)

func _input(event): 
    if Input.is_action_just_pressed("ui_up"):
        move_cursor(  0 , -1 )
        print(Input)
    elif Input.is_action_pressed("ui_down") and not event.is_echo():
        move_cursor(  0 ,  1 )
        print(Input)
    elif Input.is_action_just_pressed("ui_left") and event.is_pressed():
        move_cursor( -1 ,  0 )
        print(Input)
    elif Input.is_action_just_pressed("ui_right"):
        move_cursor(  1 ,  0 )
        print(Input)
        return

func move_cursor(x , y):
    $Sprite.position += Vector2(x , y) * TILE_SIZE
Calinou commented 3 years ago

You should always use if event.is_action_pressed() instead of Input.is_action_pressed() in the _input() method. This will handle echo rejection for you automatically :slightly_smiling_face:

fagnerln commented 3 years ago

You should always use if event.is_action_pressed() instead of Input.is_action_pressed() in the _input() method. This will handle echo rejection for you automatically slightly_smiling_face

My intention is to use is_action_just_pressed that's why I used Input as there's no function is_action_just_pressed on event.

But I tried using if event.is_action_pressed("ui_down") and just to be sure if event.is_action_pressed("ui_down") and not event.is_echo()

My intention with this messy code is to show more techniques to move the player, and none works on the d-pad

Calinou commented 3 years ago

My intention is to use is_action_just_pressed that's why I used Input as there's no function is_action_just_pressed on event.

event.is_action_pressed() acts just like Input.is_action_just_pressed().

fagnerln commented 3 years ago

I thought that event.is_action_pressed() is the same as Input.is_action_pressed() and not Input.is_action_just_pressed(), it's a bit counterintuitive. Anyway, I'll try to use "event." more but the bug still happens independent of the methodology. Sorry for the off-topic.

Calinou commented 3 years ago

Related to https://github.com/godotengine/godot/issues/21550 (but not identical judging by the description).

p-kolacz commented 3 years ago

I have the same problem. Godot 3.2.3.stable, Arch Linux, Microsoft Xbox 360 Controller

Steps to reproduce:

  1. Create new project
  2. Add node and attach script:
    
    extends Node

func _input(event): print(event.as_text())


Pressing and releasing D-pad in any direction shows:

InputEventJoypadButton : button_index=13, pressed=true, pressure=0 InputEventJoypadButton : button_index=13, pressed=true, pressure=0 InputEventJoypadButton : button_index=13, pressed=false, pressure=0 InputEventJoypadButton : button_index=13, pressed=false, pressure=0


while any other button works as expected:

InputEventJoypadButton : button_index=0, pressed=true, pressure=0 InputEventJoypadButton : button_index=0, pressed=false, pressure=0

uberflut commented 3 years ago

Same problem on godot 3.4 for windows10. It sends every Input Twice.

if Input.is_action_just_pressed("camera_right", true):
    if cardinal_count < cardinal_index.size() - 1:
        cardinal_count += 1
    else:
         cardinal_count = 0

Printing cardinal count on frame, pressing one time outputs:

0 0 0 0 1 1 2 2 2 2

Easy to fix in code with is_echo() method. (for those looking for solutions)

snoopdouglas commented 2 years ago

Same problem here, also on Windows 10. My case is a Switch Pro controller connected via Steam Input

a-wats commented 2 years ago

I'm experiencing this bug for all button inputs using an Xbox controller on Windows 10.

EzraT commented 1 year ago

Still present in Godot 3.6 beta 3, using an xbox 360 controller under Fedora 38

Edit: I also tested this on Steam Deck for good measure, and the bug doesn't seem to happen on there weirdly enough, so perhaps it is an xbox controller specific issue.

Edit: With the same xbox controller connected to my Steam Deck, testing in desktop mode, the bug does occur, so this may or may not confirm its an issue specific to xbox controllers.

Calinou commented 1 year ago

@EzraT This sounds like https://github.com/godotengine/godot/issues/76724, whose fix hasn't been cherry-picked to 3.x.

EzraT commented 1 year ago

@EzraT This sounds like #76724, whose fix hasn't been cherry-picked to 3.x.

Thank you. Is this going to be cherry picked for 3.6? I still use Godot 3 often so I would appreciate it.

Calinou commented 1 year ago

Thank you. Is this going to be cherry picked for 3.6? I still use Godot 3 often so I would appreciate it.

The PR has a cherrypick:3.x label, so yes.

Calinou commented 9 months ago

Can anyone affected by this issue test 3.6 beta4 to see if the issue is resolved there?

EzraT commented 9 months ago

Can anyone affected by this issue test 3.6 beta4 to see if the issue is resolved there?

Tested with an xbox 360 controller and still present in 3.6 beta4. System info: Fedora Linux 39 (KDE Plasma) - Wayland

fagnerln commented 9 months ago

Can anyone affected by this issue test 3.6 beta4 to see if the issue is resolved there?

I tried and it still has the issue, I even tried Godot 4 and it has too.

Maybe its a driver bug? I've no idea who I need to report.

Calinou commented 9 months ago

Maybe its a driver bug? I've no idea who I need to report.

If you can reproduce this in other games and applications that don't use Godot, it's a driver bug. Otherwise, it's a Godot bug.

fagnerln commented 9 months ago

Maybe its a driver bug? I've no idea who I need to report.

If you can reproduce this in other games and applications that don't use Godot, it's a driver bug. Otherwise, it's a Godot bug.

I never noticed double clicks in any game, and no idea how to "proof" it, so I take a look on Defold engine (I have no idea how it works) and tried to reproduce this issue, but looks like it works correctly, just printing once (not sure if it's a valid comparison).

function on_input(self, action_id, action)
    if action_id == hash("key_pressed_up") and action.pressed then
        print("Up!")
    end
    if action_id == hash("key_pressed_down") and action.pressed then
        print("Down!")
    end
    if action_id == hash("key_pressed_left") and action.pressed then
        print("Left!")
    end
    if action_id == hash("key_pressed_right") and action.pressed then
        print("Right!")
    end
end
Rindbee commented 3 months ago

Possibly related to #66878.

If it is convenient, you can use evtest/evemu-record to test the keycode mapping of the controller on Linux.

tracefree commented 2 weeks ago

I still have this issue on Godot 4.3stable. System information:

Godot v4.4.dev3 - Arch Linux # 1 SMP PREEMPT_DYNAMIC Thu, 12 Sep 2024 17:21:02 +0000 on Wayland - Wayland display driver, Single-window, 2 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1080 Ti (nvidia; 560.35.03) - AMD Ryzen 5 2600X Six-Core Processor (12 threads)