
For my February post, I’ll be writing about supporting more than 4 Xbox-style controllers in a Godot game.
Summary
The solution I’ve found to get more than 4 Xbox-style controllers to work, is to force Godot Engine to use the “DirectInput” API to handle controller input. By default, Godot uses “XInput” which has a hard-coded limit of 4 controllers. Maybe that’s to stop people from plugging more than 4 controllers into Xbox’s and developers to unofficially support it. Who knows, it’s a silly restriction. So we have to modify the Godot source code to downgrade to DirectInput, which has less features (you can read more here: https://learn.microsoft.com/en-us/windows/win32/xinput/xinput-and-directinput) All I need is thumbsticks + dpad + primary buttons so it should do. If you need any of the features of XInput (like separate trigger inputs) and more than 4 controllers, unfortunately you’re out of luck (Linux users however don’t have such trivial limitations). Then build Godot from source (this isn’t as bad as it sounds, but not great I’ll admit – at least we have this option, unlike other game engines).
Pre-requisites
To do this you’ll need some familiarity with the Windows command- prompt and a little experience coding would help.
First Step – Get Godot Source Code
To get Godot to utilise 8 controllers, we’ll need to modify the source code of Godot Engine, then build it using it’s relatively simple command-line build system. I won’t waste time re-writing the instructions from the Godot documentation site – here is the link: https://docs.godotengine.org/en/latest/contributing/development/compiling/compiling_for_windows.html. I’d recommend using the “scoop” tool. Update: due to later needing to build export templates in 32bit and 64bit, I was having issues with MinGW in 32bit, so I tried Visual Studio and it worked fine. So I’d suggest Visual Studio to minimise future problems. A big download, but free and worth it to make things work better.
Modify the Source!
Using your preferred text editor, look for the files in platform/windows/joypad_windows.cpp
and platform/windwows/joypad_windows.h
.
In joypad_windows.h, modify the line
#define XUSER_MAX_COUNT 4
To
#define XUSER_MAX_COUNT 0
Update: To make the compiler happy, you’ll need to change the following line (around line 126):
xinput_gamepad x_joypads[XUSER_MAX_COUNT];
To
xinput_gamepad x_joypads[4];
This will not let xinput take over the input of the controllers. If you thought like me, why not set it to 8? It’s because the proprietary “xinput.h” has a hard-coded limit of 4 controllers. However that alone isn’t enough. The code in joypad_windows.cpp
will pick up that the controller is an Xbox controller and try to use XInput, but the limit is now 0 so no Xbox controller will function. In joypad_windows.cpp
, modify
bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x28DE, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
...
And insert the line return false;
so it looks like:
bool JoypadWindows::is_xinput_device(const GUID *p_guid) {
return false;
static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x28DE, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
...
Combining these two, it will force all controllers to work as DirectInput and not allow XInput to take over any controllers. Thus, with the higher limit of DirectInput controllers, you can now have 8 (or more – up to 16) controllers!
Build Godot
Using the link above, build Godot with scons platform=windows
. It will take some time, depending on how powerful your processor is. On my home AMD Ryzen 5 5600G, it took maybe 10-15 minutes or so. The resulting Godot executable will be in the bin
directory. It should just run.
I could distribute my executable, but I don’t have the tools set up for signing executable files to be safe for distributing. But the steps in this tutorial shouldn’t be too difficult, especially if you’re a programmer.
Now, you should be able to plug in and use more than 4 Xbox controllers in your Godot game! (With the previously mentioned limitations above).
Motivation
I designed my game, Gravity Flux, to support up to 8 players. But when submitting my game to Steam, I didn’t check if I could actually use more than 4 XInput/Xbox controllers in Windows! Oops, slight oversight. Steam’s tester monkeys people told me that the full 8 controllers didn’t work (despite me checking “Full controller support”). Odd that they actually checked that. Maybe it was a robot/script that checked it, but how could a script recognise how to play the game? Must have been humans. Which is pretty nice. Slight setback for me but nice. So I had to remove the “Full Support” and “Partial Support” for controllers on Steam’s store page. This means those looking for controller supported games (eg Steam Deck users) won’t find it in search results for controller supported games. So, to slightly increase sale possibilities, it’s in my interests to support the 8 controllers as advertised.
My initial research into solving this problem lead me to think that I needed SteamInput incorporated into my game. So I tried that (using GodotSteam in Godot) but it didn’t support the more than 4 Xbox controllers. So I then did some more web searching, which lead me to this issue on Godot’s Github issue tracker: https://github.com/godotengine/godot/issues/19173. A closed thread requesting more than 4 XInput controllers. Obviously it didn’t get fixed. I read it further and made me look at the platform/windows
source code. Played around with some code and after some trial and error, fixed it! As someone mentioned, a slightly smarter solution would be to use XInput for the first 4, then DirectInput for the remainder. I don’t need to do that for my game so I haven’t done that, plus this tutorial is much easier to follow. I might look into implementing that idea later if there are any requests for it.