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

Xbox controller trigger input is wrong. #44178

Closed
EricEzaM opened this issue Dec 8, 2020 · 11 comments · Fixed by #56238
Closed

Xbox controller trigger input is wrong. #44178

EricEzaM opened this issue Dec 8, 2020 · 11 comments · Fixed by #56238

Comments

@EricEzaM
Copy link
Contributor

EricEzaM commented Dec 8, 2020

Godot version:
4.0 master
3.2.3 stable

OS/device including version:
WIN 10, using Wired Xbox 360 controller.

Issue description:
Godot treats trigger input incorrectly.
The for the Right trigger, first half of the trigger pull is "Joystick 2 Up", and the second half if "Joystick 2 Down", but you can only set one of these axes as the input value. This means that the first half of the trigger pull is ignored, and you essentially always have a deadzone of 50%...

Here is an example with a utility that reads what the actual input is. As you can see, Godot thinks the input starts at 50%. Note I have the deadzone set to 0% here (does deadzone even work anway??).
controller_input_trigger_wrong

Steps to reproduce:
Make an input action with a joystick input event.
Print or set a label text to Input.get_action_strength("my_action")
Play the scene and press the right trigger.
The label will only go above 0 when the trigger is half pressed.

Minimal reproduction project:
For 3.2
XboxTriggersWrong.zip

@EricEzaM
Copy link
Contributor Author

EricEzaM commented Dec 8, 2020

float val = p_value.min == 0 ? -1.0f + 2.0f * p_value.value : p_value.value;

Here is where the value gets reversed. The controller does input a value 0 to 255 (not pressed to full pressed), which then goes through a bunch of different conversions depending on the "axis". It's a bit hard to follow tbh.

I don't know why it was done like this... Why were triggers split into 2 axes where you can only use half of them?

@Calinou
Copy link
Member

Calinou commented Dec 8, 2020

I don't know why it was done like this... Why were triggers split into 2 axes where you can only use half of them?

See #38151 and #42799.

cc @madmiraal

@madmiraal
Copy link
Contributor

Why were triggers split into 2 axes where you can only use half of them?

Originally, Microsoft used a single axis for the two triggers. The -ve and +ve were split into the two triggers. To get around the problem of only being able to use one trigger at a time, they were split into two axes, but the range wasn't changed. Actually, the complexity goes back further, because originally triggers were buttons not even axes; so having a axis with a range was an enahancement.

@EricEzaM
Copy link
Contributor Author

EricEzaM commented Dec 8, 2020

@madmiraal Ok, so can this be fixed?

This is like having a deadzone of 50% all the time. This is not how it works in other engines.

@madmiraal
Copy link
Contributor

The for the Right trigger, first half of the trigger pull is "Joystick 2 Up", and the second half if "Joystick 2 Down"

The left trigger should map to the positive half of axis 4 (Joystick 2 Right) and the right trigger should map to the positive half of axis 5 (Joystick 2 Down).

I don't have an XBox controller so I can't test it and confirm that this is a bug, but the values are provided by Windows XInput. In the case of triggers these are bytes. The byte values are converted to a positive value between 0 and 1 here:

if (p_xinput) {
if (p_trigger) {
jx.min = 0;
jx.value = (float)p_val / MAX_TRIGGER;
return jx;
}

There should never by negative values provided by triggers.

@golddotasksquestions
Copy link

golddotasksquestions commented Jan 28, 2021

I have an Xbox One controller (Win 64). When I map the trigger buttons (L2,R2 - not the shoulder buttons) to left_trigger and right_trigger and

func _physics_process(_delta):
	print("right: ",Input.get_action_strength("right_trigger"))
	print("left: ",Input.get_action_strength("left_trigger"))

it will print

left: 0
right: 0
left: 0
right: 0
left: 0
right: 1
left: 1
right: 1
left: 1
right: 1

Godot 3.2.3 stable

This is strange, for one because deadzone in the Input Map was set to 0, yet the button press was only registered after it has already been pressed halve way through, and second, because I seem to remember successfully using strength on this very Xbox One controller some time back (might be more than a year) without problems. I get strength from my analog sticks on the same controller just fine.
Edit: I realized I made the mistake to use the joy button L2 R2, not the joy axis L2 R2 in the Input map. On the joy axis the triggers work fine, deadzone included.

@EricEzaM
Copy link
Contributor Author

EricEzaM commented Jan 29, 2021

Yeah from memory testing this problem deadzone doesn't do anything it seems.

It is quite counterintuitive due to the way it is set up with the 2 different axes representing the 2 halves of the trigger pressed level. Currently you can only bind to one of these axes, so you get either the first half or the second half of the trigger movement. If you use the axis which is labelles as L2 and R2 it is like having a dead zone of 50% all the time.

@madmiraal
Copy link
Contributor

@EricEzaM Is this still an issue for you? @golddotasksquestions, in his edited comment, says "On the joy axis the triggers work fine, deadzone included." with a Xbox One Controller. I have now tested this on Windows with a PS3 controller and it (including the dead zone) works fine for me too.

The only thing I can think of is the Action Deadzone, which despite you saying "I have the deadzone set to 0% here", in your MRP it is set to the default 50%; so the behaviour you're seeing would be expected.

BTW See godotengine/godot-proposals#3709 for a proposal on making the axes dead zone configurable and changing the default to a more reasonable value of 5%.

@EricEzaM
Copy link
Contributor Author

I will try and test, thanks @madmiraal

Might be in the new year tho

@madmiraal
Copy link
Contributor

@EricEzaM I've just tested this on master and I can confirm that it is a problem on master for all controllers. On 3.x it works as expected.

@golddotasksquestions
Copy link

@madmiraal I don't have access to a controller right now, but will test this again as soon as I can.

@akien-mga akien-mga added this to the 4.0 milestone Jan 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants