Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Movement doesn't work as expected when mapping keys and axes to the same action #45628

Closed
mapedorr opened this issue Feb 1, 2021 · 49 comments · Fixed by #80859
Closed

Movement doesn't work as expected when mapping keys and axes to the same action #45628

mapedorr opened this issue Feb 1, 2021 · 49 comments · Fixed by #80859

Comments

@mapedorr
Copy link

mapedorr commented Feb 1, 2021


Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.


Godot version:
3.2.4.rc1.official

OS/device including version:
Windows 10 (19042.746)

Issue description:
When I plug in a PS4 controller, KinematicBody2D doesn't move properly while using the d-pad buttons or the keyboard. Same occurs if I use DS4Windows to emulate a Xbox 360 controller (XInput).

(!) Note The same code works fine in Godot v3.2.3.stable, both for the PS4 controller (with and without DS4Windows) and the keyboard.

func _physics_process(delta):
	velocity = get_direction() * speed
	velocity = move_and_slide(velocity)


func get_direction():
	var dir: = Vector2.ZERO
	dir.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
	dir.y = Input.get_action_strength("move_down") - Input.get_action_strength("move_up")
	dir = dir.normalized()
	return dir

Steps to reproduce:

  1. Open and run the attached project with a PS4 controller connected.
  2. Move the rectangle on the screen using WASD or the arrow keys, then try to move it using the d-pad buttons.
  3. The node's movement shouldn't work properly, neither with the keyboard or the controller.
  4. Disconnect the controller and the rectangle will move without problems using the keyboard.

Repeat steps 1 and 2 in Godot v3.2.3.stable.official and the rectangle will move without problems.

Here you can see how the gamepad registers the buttons pressing without moving the rectangle, same for WASD and arrow keys.

Minimal reproduction project:

GamepadInputError.zip

@madmiraal
Copy link
Contributor

Possibly related to #44721.

I don't have access to a PS4 controller; so, to help with troubleshooting, please provide the output (which button number or numbers is reported to be pressed) for each direction of the D-Pad when running the Joypads demo under both 3.2.3-stable and 3.2.4.rc1.

@mapedorr
Copy link
Author

mapedorr commented Feb 1, 2021

Thanks @madmiraal

The button numbers for 3.2.3-stable and 3.2.4.rc1 are the same.

gamepad_error-help

Let me know if I can help with something else.

@madmiraal
Copy link
Contributor

@mapedorr I'm struggling to understand what the problem is and it's difficult to tell from the video what is happening vs what is expected. With the joystick connected, please complete the following table:

  Expected What it does in 3.2.3 What it does in 3.2.4.rc1
Doing Nothing Nothing    
W pressed      
A pressed      
S pressed      
D pressed      
D-pad Up      
D-pad Left      
D-pad Down      
D-pad Right      

@mapedorr
Copy link
Author

@madmiraal Hi, sorry for the late response and for not making clear what's going on.

  Expected What it does in 3.2.3 What it does in 3.2.4.rc1
Doing Nothing Nothing Nothing Nothing
W pressed Character moves up continiously  Works as expected  Character moves up and suddenly stops moving
A pressed Character moves left continiously  Works as expected  Character moves left and suddenly stops moving
S pressed Character moves down continiously  Works as expected  Character moves down and suddenly stops moving
D pressed Character moves right continiously  Works as expected  Character moves right and suddenly stops moving
D-pad Up Character moves up continiously  Works as expected  Character moves up and suddenly stops moving
D-pad Left Character moves left continiously  Works as expected  Character moves left and suddenly stops moving
D-pad Down Character moves down continiously  Works as expected  Character moves down and suddenly stops moving
D-pad Right Character moves right continiously  Works as expected  Character moves right and suddenly stops moving

Same occurs for diagonals (pressing two buttons at the same time).

@madmiraal
Copy link
Contributor

@mapedorr Just to clarify: It's behaving as if you've released the button when you haven't, but you don't see that in the Joypads Demo?

@mapedorr
Copy link
Author

@madmiraal Exactly \ (-^〇^-) /

@robertarnborg
Copy link

robertarnborg commented Feb 19, 2021

I am having this issue as well, my player stops and goes when using d-pad inputs in 3.2.4-rc2 not registering the key presses consistently. <:(

@madmiraal
Copy link
Contributor

This may be a duplicate of #43674 i.e. the action_strength is being reset to zero by the joystick due to a lack of a functioning deadzone.

@madmiraal
Copy link
Contributor

@mapedorr Does the problem go away if you remove the axis mappings from the Input Map move_* mappings?
@robertarnborg Do you also have D-Pad and Joystick movements mapped to the same input actions?

@mapedorr
Copy link
Author

Yes @madmiraal . The problem disappears if I remove the axis mappings. 😄

@robertarnborg
Copy link

@madmiraal yes, I have them mapped them to same action, in this case movement and the input is checking action_strength.

@madmiraal
Copy link
Contributor

Mapping multiple keys or a key and an axis to a single action is known to cause issues: see #30888 and #39287. #30890 updated the documentation for is_action_pressed() to highlight this, but the same applies to get_action_strength(), which is what is happening here. This particular scenario was less evident in 3.2.3, because small movements were been filtered out (which was causing #42876, and fixed with #43233 and backported to 3.2 with #43234) but as identified in #39287, it is a pre-existing problem that doesn't have an easy fix.

@bojidar-bg suggested, changing the behaviour of is_action_pressed() to not release until all bound buttons are released. This could be extended to get_action_strength(), by using, for example, the maximum of multiple buttons and axes.

@madmiraal madmiraal changed the title Movement doesn't work while using a controller (d-pad buttons) Movement doesn't work as expected when mapping keys and axes to the same action Feb 21, 2021
@mapedorr
Copy link
Author

I'll update my code to handle this. Thank you so much for your help @madmiraal .

@madmiraal
Copy link
Contributor

@mapedorr @robertarnborg I've created a PR (#47599) that should fix this problem. However, I don't have a PS4 controller to test it with. Please test it for us.

@jitspoe
Copy link
Contributor

jitspoe commented May 7, 2021

This GDScript workaround might help: #30890 (comment)

@DavidJVitale
Copy link

I have noticed this same behavior for v3.3.stable.mono.official . Disabling all axis input actions and just using dpad input actions fixed the problem for me. I was using an XInput controller (XBox 360)

@lucassene
Copy link

lucassene commented Jul 22, 2021

I'm using Godot 3.3.1.stable and this issue is happening still, even when I have a PS4 controller connected to the USB but turned off, only recharging. Godot recognizes it as a connected joystick and when I map both a Stick axis and a keyboard key to the same action, the input stops randomly when pressing a key.

I noticed that even with the PS4 Controller turned off, Windows recognizes it as an Audio Device.

image
"Remover dispositivo" = Remove device

Is there a way to ignore joystick inputs besides removing them from the input mapping?

@Calinou
Copy link
Member

Calinou commented Jul 22, 2021

Is there a way to ignore joystick inputs besides removing them from the input mapping?

There's currently no way to disable controller support entirely, but I suppose that will need to be added eventually (e.g. with a project setting and --no-gamepad CLI argument).

feldc added a commit to ShiningForceRemade/SFR-Godot-3-old- that referenced this issue Aug 8, 2021
… support)

Currently the 3.2.X and 3.3.X branches of Godot seem to have issues having multiple actions set to the same input.
godotengine/godot#45628 (issue)
When a joystick axis and a dpad direction are put together the added joystick axis breaks the dpad behaviour. Resulting in the dpad
stoping randmonly after a couple of presses (ranges from 1 to 6 presses before stopping fully).
4.0 should have a fix for this review support then or if the fix is backported to the >=3.3.X series of Godot versions.
godotengine/godot#47599 (fix)
@puzzud
Copy link

puzzud commented Jul 30, 2023

@joemicmc, I was recently hunting this issue with my game and someone playing it through a Steam Deck. Fortunately (unfortunately), someone else reported similar behavior with a different device entirely. Through testing, the different device was issuing axis events along with dpad events.

But from what I can tell with the Steam Deck's virtual controller, once it's engaged (at least with Godot) it fires off a continuous flurry of axis events at close to 0.0 levels. I believe this behavior is a mistake in the Steam Deck (hardware or software--I don't know). The resulting behavior is that even if you are listening for action events via _input, even if you are just using dpad, unwarranted axis events most likely registering under the action's dead zone will "unpress" the behavior you may have associated with dpad. And depending on how things are engineered, wonky behavior can ensue.

What does this have to do with the "different device"? Well, I had to tighten up my input processing to be robust enough to deal with both nonsensical & unexpected behavior. An easy & less ideal way out is to decouple the game pad axis from the action associated with your dpad. I'd recommend doing that unless you really need both to work.

@jordanlis
Copy link

jordanlis commented Jul 30, 2023

I have the exact same issue : my controller, when plugged, is throwing some random events (the left joystick), and it calls the actions which is mapped to the "d" key of the keyboard.

I understand that this #47599 will fix the issue.

But why do we have a deadzone parameter in the "controls" section of godot if it doesn't apply ?
image

I mean, the events of the joystick are really small, something like 0.17, but it still sends the event wheareas the deadzone parameter is defined at 0.5 ?

I don't understand why it throw events if we have this 0.5 deadzone...
image

From my point of view, the deadzone parameter is not working as expected, no ?

@puzzud
Copy link

puzzud commented Jul 30, 2023

From my point of view, the deadzone parameter is not working as expected, no ?

@jordanlis, I agree in that I was thrown off by these events coming in despite the dead zone. But when you think about it, you have to get at least one event that registers under the dead zone, in order to report the action is not "pressed". So either it is up to Godot to filter out redundant events or the onus is on Godot clients.

I believe you are advocating the former.

Note that even if that was done, it wouldn't resolve the issue @hawkerm is having. In which case, I don't think Godot can be made generally intelligent enough to handle every case without potentially stomping on another. I could be wrong.

That being said. If Godot did try to reduce redundant axis events above and below the set dead zone, it certainly would save a lot of headache.

@jordanlis
Copy link

jordanlis commented Jul 30, 2023

From my point of view, the deadzone parameter is not working as expected, no ?

@jordanlis, I agree in that I was thrown off by these events coming in despite the dead zone. But when you think about it, you have to get at least one event that registers under the dead zone, in order to report the action is not "pressed". So either it is up to Godot to filter out redundant events or the onus is on Godot clients.

I believe you are advocating the former.

Well, first I don't understand the deadzone feature (how is it useful if it doesn't work as it should ?)
Anyway, I'm not telling what Godot dev should do, but then If the deadzone doesn't work, without any development the issue can't be solved from what I understand. I mean I don't have any trick to prevent the d key to be released when my controller weirdly throw some events without me touching it.
So my character just stops moving at all because of that, and I wish I would have a solution by script to prevent that but it's not possible.

From what I understand the only solutions are :

  • disconnecting the controller
  • stop assigning keys and joysticks to the same action

I just wish I could have another solution. Anyway I can be patient and wait for a next release.

Note that even if that was done, it wouldn't resolve the issue @hawkerm is having. In which case, I don't think Godot can be made generally intelligent enough to handle every case without potentially stomping on another. I could be wrong.

That being said. If Godot did try to reduce redundant axis events above and below the set dead zone, it certainly would save a lot of headache.

Totally agree on that

@mubinulhaque
Copy link

@jordanlis You can use jakeymg's workaround here, for now.

@jordanlis
Copy link

@jordanlis You can use jakeymg's workaround here, for now.

It seems to be a solution for dpad and joystick. Maybe it can be done the same way with keyboard / controller... I'll have to test. These days, I didn't have any issues with this joystick, the joystick seems more stable. Anyway. I know where to look when I'll try to fix it in the future.

@Zireael07
Copy link
Contributor

"Device sending a flurry of events" is usually a sign of broken device and/or drivers, so it's alarming to hear that Steam Deck exhibits that behavior (it's too new to be a hardware fault)

Definitely means this issue should be given a higher priority (not to mention it's blocking an important QoL PR )

@puzzud
Copy link

puzzud commented Aug 8, 2023

is usually a sign of broken device and/or drivers, so it's alarming to hear that Steam Deck exhibits that behavior (it's too new to be a hardware fault)

@Zireael07, yea I was surprised to see it. A user reported the associated behavior to me so I bought a Steam Deck and saw it on my own as well. The odd thing is joystick deadzones can be set & tested on a Steam Deck--when I tested mine I saw no visible jitter or movement outside the default deadzones. Worth noting again that I saw the "flurry" only after any button on the deck is engaged; until then it is silent. My gut intuition says that it's likely a software meets hardware issue on the Steam Deck's side, closely associated with behavior of the "Steam Virtual Gamepad".

Where might such an issue be reported? I assumed noting the behavior here was sufficient enough, given Valve stated they "talk to Godot" 😂:
https://partner.steamgames.com/doc/steamdeck/faq

@mubinulhaque
Copy link

Where might such an issue be reported? I assumed noting the behavior here was sufficient enough, given Valve stated they "talk to Godot" 😂: https://partner.steamgames.com/doc/steamdeck/faq

Did they? I have not seen any Valve employee even talk about this engine, much less add to it.

My gut intuition says that it's likely a software meets hardware issue on the Steam Deck's side, closely associated with behavior of the "Steam Virtual Gamepad".

Considering that this is happening with other controllers while Steam is not running, I think it's safe to say that it's probably not Steam and more of a logic error.

@keir
Copy link

keir commented Aug 17, 2023

I have this issue with a PlayStation DualShock 4 controller on both a Windows system and a macOS system, with Godot 4.1.1. The reproduction was the same as others are seeing here: buttons randomly stop reporting being pressed. Since I am new-ish to Godot, it wasn't obvious whether I was doing something wrong or if the issue was with the engine. Unfortunately, I lost half of a vacation day to tracking down the root issue (combining buttons and joystick inputs). I got to learn a bit about Godot in the process, so it wasn't entirely wasted, but I can't imagine the Godot maintainers want new users to go through this frustrating experience.

If the Godot maintainers are not ready to merge the proposed patch, please consider adding a warning in the Input Map dialog that says "Combining Joystick and Button presses in the input map is not supported: see issue #45628"; or disable combining buttons with joystick axes entirely. The warning/error would have saved frustration; and I can see from the comments on this issue it would help others as well.

@keir
Copy link

keir commented Aug 17, 2023

For others who run into this, here is my workaround:

For player input handling, the following picks the greater of button or analog input:

func get_vector_for_input_prefix(prefix) -> Vector2:
	return Input.get_vector(prefix + "move_left", prefix + "move_right", prefix + "move_up", prefix + "move_down")

func _physics_process(delta):
	# Workaround bug when mapping both buttons and analog inputs to a single event:
	#
	#    https://github.com/godotengine/godot/issues/45628
	#
	# If the bug is fixed, switch the below block of code to simply:
	#
	#   var input: Vector2 = Input.get_vector("left", "right", "up", "down")
	#
	var input: Vector2 = Vector2.ZERO
	var analog_input: Vector2 = get_vector_for_input_prefix("analog_")
	var button_input: Vector2 = get_vector_for_input_prefix("button_")
	if analog_input.length() > button_input.length():
		input = analog_input
	else:
		input = button_input

	velocity = input * SPEED_PIXELS_PER_SEC / delta
	move_and_slide()

The input map looks like this:
Screenshot 2023-08-17 at 1 20 34 PM

Keywords to help others find this issue and workaround: Input.get_vector, Input.is_action_pressed, joystick, buttons, character movement

@Aurelynn
Copy link

I'm completely new with godot since a few days ago and immediately ran into this issue in my first 30 minutes of making a project and trying to make a character move. I had no idea this had anything to do with a controller being connected so it took me days to figure out this was the issue.

I did figure out that 4.0 and 4.0.4 don't seem to have this issue at least for me. I only have this problem in 4.1 and 4.1.1.

In my completely clueless opinion as someone new to the engine, maybe the default behavior for godot should be to only accept inputs from either controllers or keyboards, not both at the same time? If this kind of functionality is wanted it should be a choice by the developer? Or go back to the handling in 4.0 where this wasn't an issue?

@Calinou
Copy link
Member

Calinou commented Aug 20, 2023

I did figure out that 4.0 and 4.0.4 don't seem to have this issue at least for me. I only have this problem in 4.1 and 4.1.1.

This issue isn't new in 4.1. It's also present in 3.x.

In my completely clueless opinion as someone new to the engine, maybe the default behavior for godot should be to only accept inputs from either controllers or keyboards, not both at the same time?

It's likely feasible to ignore inputs that don't come from the last used device type (controller or keyboard), but a proper fix will probably require not much more effort than a workaround like that.

@KoBeWi
Copy link
Member

KoBeWi commented Aug 22, 2023

I can't reproduce this bug in 4.2 dev using the attached project.
I tested with Xbox controller though.

@akien-mga akien-mga added this to the 4.2 milestone Aug 29, 2023
@joemicmc
Copy link

Oooh, I will test in the next 4.2 release with my Steam Deck as that is where I saw issue.

@fractilegames
Copy link

Nice. Will this fix end up in 3.6 too at some point?

@Calinou
Copy link
Member

Calinou commented Aug 29, 2023

Nice. Will this fix end up in 3.6 too at some point?

Yes (if the fix is confirmed to work correctly), but the fix can't be trivially cherry-picked. It shouldn't be too difficult to redo for 3.x, but a new PR needs to be opened.

Edit: This issue needs to be fixed first: #81164

@slumberface
Copy link

The following issue described in #68433 is still happening on 4.2-beta1:

One axis should be 1, the other 0 if you press a single key, however I get values such as (0.998444, 0.055762) if either:

- the application has just started, or
- for a short while after using the controller.

I have found this to be true if a ps5 dualsense is plugged in while pressing keys. When the dual sense is unplugged, this does not happen to the keyboard inputs.

@Jantho1990
Copy link
Contributor

Jantho1990 commented Nov 1, 2024

This is still an issue for me on Godot 3.6. I confirmed using the sample project.

Used a PS4 DualShock controller, Windows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment