You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tested versions are every 4.x release, including dev releases. Currently on 4.4 dev 6
System information
Windows 10 (any) and C#
Issue description
Godot 4 users are expected to add inputs via the Input Map in the settings. This is similar to Unity's "New" input system. However, Godot's input actions are per-device
So if you are making a complicated game (like we are), where there are dozens of inputs, you will have to duplicate each of those dozens 4 times for each device. In our case this would lead to 200+ actions and you'd have to hope there are 0 mistakes. This is horrible. And what if you want to change bindings in-game? Just give up. If you go with "All Devices" like in that image, then any device will trigger the action, instead of for one player.
We decided to instead go with the classic approach of "assigning" a device to each player in the game. You're told to do this all over the web anyway so you might as well.
In C# you do this with Input.JoyConnectionChanged += Blabla;
This lets you know when a new joypad is connected and when an existing one disconnects. Fantastic, now I can assign a device to a player and then poll for the button presses per device!
Nope you're wrong again because the "device" ids are not unique. So if I want player 0 to use device 0, player 1 to use device 3, player 2 to use device 1 and player 3 to use device 2, then you're out of luck. The Input Map also won't cover you there.
What's wrong, why can't this work? Well, firstly the input system seems to break if two of the same controller kind are connected at once, for example 2 PS4 Controllers. Input.GetJoyInfo() returns a blank dictionary for some reason, even on Windows where the documentation says it clearly does not. Each device has the same Guid and name as well so no way of knowing which is which. You're told to go strictly by device ID but these device IDs are not even what the cpp backend of Godot is using. And you're given no objects or handles to hold so again there really is no way to assign a joypad to a specific user. Not to mention, InputEventJoypadMotion is never reported in certain Control nodes under _GuiInput() (no idea how to tell if it will work or not either).
Also, we have had 0 Xbox controllers work in Godot ever since we started using it in March 2024, EVEN WITH the Input Map. Yes it really has been over 9 months of updates and not once has an xbox controller returned any inputs on any windows system we tried. It doesn't matter if it's in the editor, exported, release/debug etc. They are notified with Input.JoyConnectionChanged but every type of polling you do results in default values (axis is 0, no vibration, buttons are never pressed). So it's like they're shadowbanned from Godot. But somehow PS4, switch, snes, 8bitdo, and knockoff controllers work in Godot flawlessly. If we try to use steam input with an xbox controller, the buttons are all wrong (LB is somehow A, Y is Start etc). This is beyond insane and I don't know how to feel about it other than baffled. It definitely works fine in Godot 3, of which many games support it, but alas here we are in Godot 4 with no xbox support. If it's working for you, CONGRATULATIONS you have won the lottery or something! Please share your secret.
Even when you do get a joypad, you don't know what type it is (so we can show relevant button icons) unless you do a switch statement on its name and filter by known names. But when it comes to knockoff and third-party controllers, good luck maintaining that huge list yourself.
The other great thing about the non-unique device IDs is the fact that they are incorrectly reported (at least in C#, idk about gdscript). You can disconnect device 0 and it says "wow device 1 was disconnected!". Then the other devices that are still connected (which you assume one of them got set to device 0) report no inputs when polling device 0. So yeah there's no way to have controller splitscreen with Godot (at least in C#. I am not trying gdscript).
So my solution is to just include SDL's binaries in the project, similar to steam's binaries, and make my own entire SDL wrapper and completely ignore godot's Input system since it doesn't function. Yes this will bite us in the ass when we are porting to console. Yes it is necessary. Yes it was easier and yes it works.
This issue is mostly a rant but it is backed with only facts. There are too many broken things to focus on and make 111111 issues about. I'm not sure how this engine existed this many years with these issues without outrage. I guess everyone who attempts controller multiplayer just gives up or goes back to Unity. If this ever gets fixed, great, but I really don't expect it to anytime soon. I still care a lot about Godot's future but it's hard to look at a shortcoming this bad and not be upset. That's why I made this issue at all.
privatestaticvoidInput_JoyConnectionChanged(longdevicee,boolconnected){// TODO: Godot is broken af// Having 2 PS4 controllers plugged in gives you [0, 1] as expected but info for both is empty even on windows// Disconnecting either of the controllers results in joy 1 being disconnected// Then polling for input on device 0 still returns nothing even though supposedly GetConnectedJoypads() is [0]// So if I wanted to assign device 0 or 1 to someone, it's impossible, since these values mean nothingintdevice=(int)devicee;// Why are you even giving me a long?stringinfo=Input.GetJoyInfo(device).ToString();// TODO: Why is info empty?DebugLog($"Joy connection: Device={devicee} | Name=\"{Input.GetJoyName(device)}\" | ID={Input.GetJoyGuid(device)} | Info={info} | List={Input.GetConnectedJoypads()} | Connected={connected}");}
@ We are told that blue is device 0 and black is device 1, so let's see if you lied to me :)
@ Blue controller assigned to my player (so I can poll inputs on device 0) Input ► Player 0 now using JoyPad: Device=0 | Name="PS4 Controller"
@ Polling inputs on device 0...
@ Successfully detects movement on the blue controller, and no movement on the black.
@ Polling inputs on device 0...
@ No inputs are detected from the black (which is presumably device 0)
@ But the inputs are being polled from the blue controller (which we're told is device 1)
Tested versions
Tested versions are every 4.x release, including dev releases. Currently on 4.4 dev 6
System information
Windows 10 (any) and C#
Issue description
Godot 4 users are expected to add inputs via the Input Map in the settings. This is similar to Unity's "New" input system. However, Godot's input actions are per-device
So if you are making a complicated game (like we are), where there are dozens of inputs, you will have to duplicate each of those dozens 4 times for each device. In our case this would lead to 200+ actions and you'd have to hope there are 0 mistakes. This is horrible. And what if you want to change bindings in-game? Just give up. If you go with "All Devices" like in that image, then any device will trigger the action, instead of for one player.
We decided to instead go with the classic approach of "assigning" a device to each player in the game. You're told to do this all over the web anyway so you might as well.
In C# you do this with
Input.JoyConnectionChanged += Blabla;
This lets you know when a new joypad is connected and when an existing one disconnects. Fantastic, now I can assign a device to a player and then poll for the button presses per device!
Nope you're wrong again because the "device" ids are not unique. So if I want player 0 to use
device 0
, player 1 to usedevice 3
, player 2 to usedevice 1
and player 3 to usedevice 2
, then you're out of luck. The Input Map also won't cover you there.What's wrong, why can't this work? Well, firstly the input system seems to break if two of the same controller kind are connected at once, for example 2 PS4 Controllers. Input.GetJoyInfo() returns a blank dictionary for some reason, even on Windows where the documentation says it clearly does not. Each device has the same Guid and name as well so no way of knowing which is which. You're told to go strictly by device ID but these device IDs are not even what the cpp backend of Godot is using. And you're given no objects or handles to hold so again there really is no way to assign a joypad to a specific user. Not to mention,
InputEventJoypadMotion
is never reported in certainControl
nodes under_GuiInput()
(no idea how to tell if it will work or not either).Also, we have had 0 Xbox controllers work in Godot ever since we started using it in March 2024, EVEN WITH the Input Map. Yes it really has been over 9 months of updates and not once has an xbox controller returned any inputs on any windows system we tried. It doesn't matter if it's in the editor, exported, release/debug etc. They are notified with
Input.JoyConnectionChanged
but every type of polling you do results in default values (axis is 0, no vibration, buttons are never pressed). So it's like they're shadowbanned from Godot. But somehow PS4, switch, snes, 8bitdo, and knockoff controllers work in Godot flawlessly. If we try to use steam input with an xbox controller, the buttons are all wrong (LB is somehow A, Y is Start etc). This is beyond insane and I don't know how to feel about it other than baffled. It definitely works fine in Godot 3, of which many games support it, but alas here we are in Godot 4 with no xbox support. If it's working for you, CONGRATULATIONS you have won the lottery or something! Please share your secret.Even when you do get a joypad, you don't know what type it is (so we can show relevant button icons) unless you do a switch statement on its name and filter by known names. But when it comes to knockoff and third-party controllers, good luck maintaining that huge list yourself.
The other great thing about the non-unique device IDs is the fact that they are incorrectly reported (at least in C#, idk about gdscript). You can disconnect
device 0
and it says "wowdevice 1
was disconnected!". Then the other devices that are still connected (which you assume one of them got set todevice 0
) report no inputs when polling device 0. So yeah there's no way to have controller splitscreen with Godot (at least in C#. I am not trying gdscript).So my solution is to just include SDL's binaries in the project, similar to steam's binaries, and make my own entire SDL wrapper and completely ignore godot's Input system since it doesn't function. Yes this will bite us in the ass when we are porting to console. Yes it is necessary. Yes it was easier and yes it works.
This issue is mostly a rant but it is backed with only facts. There are too many broken things to focus on and make 111111 issues about. I'm not sure how this engine existed this many years with these issues without outrage. I guess everyone who attempts controller multiplayer just gives up or goes back to Unity. If this ever gets fixed, great, but I really don't expect it to anytime soon. I still care a lot about Godot's future but it's hard to look at a shortcoming this bad and not be upset. That's why I made this issue at all.
Steps to reproduce
Simplest repro with 2 PS4 controllers:
C# setup:
...
Results:
@ Blue controller connected
Input ► Joy connection: Device=0 | Name="PS4 Controller" | ID=030000004c050000cc09000000000000 | Info={ } | List=[0, 1] | Connected=True
@ Black controller connected
Input ► Joy connection: Device=1 | Name="PS4 Controller" | ID=030000004c050000cc09000000000000 | Info={ } | List=[0, 1] | Connected=True
@ We are told that blue is
device 0
and black isdevice 1
, so let's see if you lied to me :)@ Blue controller assigned to my player (so I can poll inputs on device 0)
Input ► Player 0 now using JoyPad: Device=0 | Name="PS4 Controller"
@ Polling inputs on
device 0
...@ Successfully detects movement on the blue controller, and no movement on the black.
@ Blue controller DISconnected
Input ► Joy connection: Device=1 | Name="" | ID= | Info={ } | List=[0] | Connected=False
@ Blue controller REconnected
Input ► Joy connection: Device=1 | Name="PS4 Controller" | ID=030000004c050000cc09000000000000 | Info={ } | List=[0, 1] | Connected=True
@ Polling inputs on
device 0
...@ No inputs are detected from the black (which is presumably
device 0
)@ But the inputs are being polled from the blue controller (which we're told is
device 1
)@ Black controller DISconnected
Input ► Joy connection: Device=1 | Name="" | ID= | Info={ } | List=[0] | Connected=False
@ Black controller REconnected
Input ► Joy connection: Device=1 | Name="PS4 Controller" | ID=030000004c050000cc09000000000000 | Info={ } | List=[0, 1] | Connected=True
@ Polling inputs on
device 0
...@ Inputs are still detected on the blue controller and not black.
Minimal reproduction project (MRP)
See the steps to reproduce.
The text was updated successfully, but these errors were encountered: