• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Xbox Series Controller Showing as 2 Separate Devices?

Hello,

While I was testing out the Xbox Series Controller in my game, at first I saw that it was working the way it should, but later on I noticed that I think it's actually registering as 2 separate devices. At first, I thought it might just be the way I had my controller setup working, since I check for the Description then set mapping. Since I saw in the debug log that it is showing 2 descriptions. "XInput STANDARD GAMEPAD" and "Bluetooth LE XINPUT compatible input device". Also, the "Bluetooth LE XINPUT compatible input device". shows it connects to slot 4. So, the 2nd device is Direct Input? They both usually connect at the same time and 1 controller controls both player 1 and player 2.

I just tested it with the "Twin Stick Shooter GML" project by YoYo Games and it appears it is registering as 2 sperate devices, since in the Twin Stick project, each time a controller is connected, a player object is created. So, instead of creating just 1 player object, 2 are created when connecting the Xbox Series Controller. I don't have another controller connected without knowing since it doesn't show any others are connected. I attached an image of what it shows on screen.

How could this be fixed? One way I know of, would be to say something like: if gamepad_get_description(i,) doesn't equal "Bluetooth LE XINPUT compatible input device" then assign to player.

Has anyone else noticed this?

Xbox Series Controller Description.png
 

kburkhart84

Firehammer Games
The issue is caused by XInput devices having both XInput AND DInput drivers. Since Gamemaker handles those separately, it picks up two devices. In my input system, I handle it by only allowing one input device to be detected at a time(when the player hits buttons for input mapping). Then, I prioritize the XInput devices(numbers 0 - 3). So for input mapping, you click a button(like to remap the jump button). The system then polls inputs, waiting on you to hit the button you want to map to the jump action. Each frame, it checks ALL the connected gamepads(along with keyboard and mouse). It check the XInput ones first, and if it finds one, it no longer checks the DInput device. So it would pick up device 0, but NOT device 4 in this case.

That's how I handle it. Since you are using a pre-made example, you would have to change the code somehow. Instead of adding players automatically based on device connection, you would probably want to add them via other means(like GUI buttons), and then assign devices/inputs in a separate thing. That's how Firehammer Input works. I hate the idea of assigning devices to players, because there happen to be players who do strange things, like wanting to use keyboard keys along with a gamepad's axes. If you are assigning devices, it would add artificial limits. Furthermore, it is could get slightly more complicated if they ever provide native drivers for the Switch Joycons because those come up as 2 devices(though they aren't supported without additional 3rdparty software). So this is why I don't assign devices at all, and I just have the players directly hit the inputs they want to assign to actions as part of the action mapping process.
 
The issue is caused by XInput devices having both XInput AND DInput drivers. Since Gamemaker handles those separately, it picks up two devices. In my input system, I handle it by only allowing one input device to be detected at a time(when the player hits buttons for input mapping). Then, I prioritize the XInput devices(numbers 0 - 3). So for input mapping, you click a button(like to remap the jump button). The system then polls inputs, waiting on you to hit the button you want to map to the jump action. Each frame, it checks ALL the connected gamepads(along with keyboard and mouse). It check the XInput ones first, and if it finds one, it no longer checks the DInput device. So it would pick up device 0, but NOT device 4 in this case.

That's how I handle it. Since you are using a pre-made example, you would have to change the code somehow. Instead of adding players automatically based on device connection, you would probably want to add them via other means(like GUI buttons), and then assign devices/inputs in a separate thing. That's how Firehammer Input works. I hate the idea of assigning devices to players, because there happen to be players who do strange things, like wanting to use keyboard keys along with a gamepad's axes. If you are assigning devices, it would add artificial limits. Furthermore, it is could get slightly more complicated if they ever provide native drivers for the Switch Joycons because those come up as 2 devices(though they aren't supported without additional 3rdparty software). So this is why I don't assign devices at all, and I just have the players directly hit the inputs they want to assign to actions as part of the action mapping process.
The way I have it set up, players are already created before assigning the controllers. I was just using the Twin Stick project as an example.

I'll just have to block assignment of the "Bluetooth LE XINPUT compatible input device", since it is already technically assigning the Controller as an XInput Controller.

Also, I don't really have a problem using a Joy-Con with my game and it connecting. It connects as only 1 device, but only the Right Joy-Con works. Sometimes the movement and buttons acting like they have lag. But for the most part it works. The Left Joy-Con doesn't give any input for some reason.
 

kburkhart84

Firehammer Games
The way I have it set up, players are already created before assigning the controllers. I was just using the Twin Stick project as an example.
I thought that might be the case, that you were just using it to see if your project had an issue or if it was a more general thing.

I'll just have to block assignment of the "Bluetooth LE XINPUT compatible input device", since it is already technically assigning the Controller as an XInput Controller.
That's basically what I'm doing...if I detect input from 0 - 3, I skip checking ids 4 - 12. And the way I'm mapping inputs, it directly assigns an id and a button/axis/POV so once you are checking actions it won't know or care that there is a duplicate device, it only checks the one that was assigned. And you certainly want the XInput version because the DInput version of the drivers has limitations, like the shoulder buttons' axes being the put as the same axis.

Also, I don't really have a problem using a Joy-Con with my game and it connecting. It connects as only 1 device, but only the Right Joy-Con works. Sometimes the movement and buttons acting like they have lag. But for the most part it works. The Left Joy-Con doesn't give any input for some reason.
If it is working, then I guess you DO have a problem with it. Unless things have changed, there isn't really a 1st party driver for Windows for those things, so it makes sense that you would have issues. I know Windows bluetooth picks them up and can pair, but that doesn't mean that input systems can fully use them.
 
That's basically what I'm doing...if I detect input from 0 - 3, I skip checking ids 4 - 12. And the way I'm mapping inputs, it directly assigns an id and a button/axis/POV so once you are checking actions it won't know or care that there is a duplicate device, it only checks the one that was assigned. And you certainly want the XInput version because the DInput version of the drivers has limitations, like the shoulder buttons' axes being the put as the same axis.
Well, after trying to block the assignment of the device, it seems to still come through. I'm using this to try to block it from even assigning, but for some reason it still connects.

GML:
if gamepad_get_description(i) != "Bluetooth LE XINPUT compatible input device" {
    global.Controller_Slot[i] = async_load[? "pad_index"];
}
I can't block the entire controller, because it registers as an XInput STANDARD GAMEPAD. I wonder why they made the Xbox Series controller that way?
 

kburkhart84

Firehammer Games
Well, after trying to block the assignment of the device, it seems to still come through. I'm using this to try to block it from even assigning, but for some reason it still connects.
The issue I think is that you are trying to block with descriptions as the condition...I don't count on that at all. But then I don't assign gamepads at all...I only assign individual inputs. So basically, the player initiates a search that would pick up the next pressed button(which would then get assigned to some action). The loop checks the keyboard, mouse, and gamepads, and for the gamepads, it checks #0-3 before checking #4-11. If it picks one up in the first 4, the search stops. This means that even though it would have picked up the one from 4 - 11 from the duplicate device, it never acknowledges it because it stops on the first device. Then, that device and that button(or axis) is stored in the assignment for the mapping. Finally, each loop as the system updates the status of all the actions, it only ever checks that correct gamepad ID and never knows or cares about the other one.

The main difference is that I'm not assigning gamepads at all. I'm only assigning gamepad/input pairs to actions directly upon receiving button presses. And I'm not using the async event for that purpose of course. My method skips all of that.

I wonder why they made the Xbox Series controller that way?
I can certainly say at the least that this isn't an issue with Gamemaker itself, it is a commonly found issue. The catch is that some modern game engines and games only support XInput these days and so they avoid the issue since they don't even try using the older devices. And the ones that do likely do the same thing as I do, although those may actually assign gamepads, but using the same method as I do. It may be possible to use something like the GUIDs to directly notice the duplicate and therefore choose one over the other.

As far as why Microsoft did it...my understanding is that they wanted XInput to replace DirectInput. So they chose to not implement the full functionality of the controller in the DirectInput version, making XInput the only way to get the full capabilities of the controllers. This doc page explains the differences(though it doesn't explain the reasons why they did it of course). It even has code for a way to skip the DInput version of the controller(in C++). The issue I'd guess is that Gamemaker is actually using SDL instead, and so I don't know if there is an easy way to do the same thing, and if there is, they likely just chose not to do it. So I just work around it by skipping the DInput devices when the XInput one picks something up.
 
The issue I think is that you are trying to block with descriptions as the condition...I don't count on that at all. But then I don't assign gamepads at all...I only assign individual inputs. So basically, the player initiates a search that would pick up the next pressed button(which would then get assigned to some action). The loop checks the keyboard, mouse, and gamepads, and for the gamepads, it checks #0-3 before checking #4-11. If it picks one up in the first 4, the search stops. This means that even though it would have picked up the one from 4 - 11 from the duplicate device, it never acknowledges it because it stops on the first device. Then, that device and that button(or axis) is stored in the assignment for the mapping. Finally, each loop as the system updates the status of all the actions, it only ever checks that correct gamepad ID and never knows or cares about the other one.

The main difference is that I'm not assigning gamepads at all. I'm only assigning gamepad/input pairs to actions directly upon receiving button presses. And I'm not using the async event for that purpose of course. My method skips all of that.

I can certainly say at the least that this isn't an issue with Gamemaker itself, it is a commonly found issue. The catch is that some modern game engines and games only support XInput these days and so they avoid the issue since they don't even try using the older devices. And the ones that do likely do the same thing as I do, although those may actually assign gamepads, but using the same method as I do. It may be possible to use something like the GUIDs to directly notice the duplicate and therefore choose one over the other.

As far as why Microsoft did it...my understanding is that they wanted XInput to replace DirectInput. So they chose to not implement the full functionality of the controller in the DirectInput version, making XInput the only way to get the full capabilities of the controllers. This doc page explains the differences(though it doesn't explain the reasons why they did it of course). It even has code for a way to skip the DInput version of the controller(in C++). The issue I'd guess is that Gamemaker is actually using SDL instead, and so I don't know if there is an easy way to do the same thing, and if there is, they likely just chose not to do it. So I just work around it by skipping the DInput devices when the XInput one picks something up.
Maybe you're not understanding what I'm saying. This is the first time I've encountered a Controller that registers as 2 different devices. The Xbox One Controller is just XInput as far as I see it through GameMaker. But the Xbox Series Controller is registering as 2 devices. But the GUID is the same for both devices. But, after the "XInput STANDARD GAMEPAD" description, it should show the GUID on the next line, but it just says none. After the "Bluetooth LE XINPUT compatible input device" it shows the Controllers GUID. Both of these descriptions are from the same controller.

Also, it looks like both the Xbox One Controller and Xbox Series Controller have the same GUID. So, if I blocked the Xbox Series Controller by GUID, I would also block the Xbox One Controller. But, I don't know why it's not blocking it based on it's description, since it's different.

This is what the console log shows when starting the game while the Xbox Series Controller is connected to Windows 10.

Audio group 1 -> Loaded
Audio group 2 -> Loaded
Assigned Pad 0 to Player 0
XInput STANDARD GAMEPAD
none
Assigned Pad 4 to Player 1
Bluetooth LE XINPUT compatible input device
5e04130b000000000000504944564944
Audio group 1 -> Unloading...
Audio group 2 -> Unloading...

As far as Direct Input Controllers go, I don't have a big problem with them connecting or assigning mapping. It's just that the Xbox Series Controller gets assign to the Player1 and then the 2nd device gets assigned to Player2. Which then controls both players. So if someone wanted to play my game in 2 player mode with Player 1 using a Xbox Series controller, they would end up controlling both Players.

All I want to do is to prevent the Xbox Series Controller from assigning the Direct Input side to the 2nd player.
 
Last edited:

kburkhart84

Firehammer Games
Maybe you're not understanding what I'm saying. This is the first time I've encountered a Controller that registers as 2 different devices. The Xbox One Controller is just XInput as far as I see it through GameMaker. But the Xbox Series Controller is registering as 2 devices. But the GUID is the same for both devices. But, after the "XInput STANDARD GAMEPAD" description, it should show the GUID on the next line, but it just says none. After the "Bluetooth LE XINPUT compatible input device" it shows the Controllers GUID. Both of these descriptions are from the same controller.

Also, it looks like both the Xbox One Controller and Xbox Series Controller have the same GUID. So, if I blocked the Xbox Series Controller by GUID, I would also block the Xbox One Controller. But, I don't know why it's not blocking it based on it's description, since it's different.

This is what the console log shows when starting the game while the Xbox Series Controller is connected to Windows 10.

Audio group 1 -> Loaded
Audio group 2 -> Loaded
Assigned Pad 0 to Player 0
XInput STANDARD GAMEPAD
none
Assigned Pad 4 to Player 1
Bluetooth LE XINPUT compatible input device
5e04130b000000000000504944564944
Audio group 1 -> Unloading...
Audio group 2 -> Unloading...

As far as Direct Input Controllers go, I don't have a big problem with them connecting or assigning mapping. It's just that the Xbox Series Controller gets assign to the Player1 and then the 2nd device gets assigned to Player2. Which then controls both players. So if someone wanted to play my game in 2 player mode with Player 1 using a Xbox Series controller, they would end up controlling both Players.

All I want to do is to prevent the Xbox Series Controller from assigning the Direct Input side to the 2nd player.
I understand the problem, but there isn't anything you can do to stop the async events running for the duplicate device. That's why I don't use those when assigning action mapping stuff. If you really want to assign whole devices to players(which many games do, even though I personally don't like it), then do it some time later on instead of in an automatic fashion with detected gamepads.

I wasn't fully aware of the GUID problems and those being duplicates, but in a certain way it makes sense because XInput devices simply aren't the same beasts as old school DInput ones are. So you can't block using them...but you CAN block if you do it the way I'm doing it. Don't create players right away based on the async event. Instead, use normal UI functionality to decide how many players there are, and then have each player hit a button on their gamepad at appropriate times. Then, while searching for the gamepads, go through #0 - 3 first, and only go through 4 - 11 if nothing is pressed on #0 - 3. This way, even though you would detect something on the duplicates, you don't actually get to that point because the loop stops.
 
I understand the problem, but there isn't anything you can do to stop the async events running for the duplicate device. That's why I don't use those when assigning action mapping stuff. If you really want to assign whole devices to players(which many games do, even though I personally don't like it), then do it some time later on instead of in an automatic fashion with detected gamepads.

I wasn't fully aware of the GUID problems and those being duplicates, but in a certain way it makes sense because XInput devices simply aren't the same beasts as old school DInput ones are. So you can't block using them...but you CAN block if you do it the way I'm doing it. Don't create players right away based on the async event. Instead, use normal UI functionality to decide how many players there are, and then have each player hit a button on their gamepad at appropriate times. Then, while searching for the gamepads, go through #0 - 3 first, and only go through 4 - 11 if nothing is pressed on #0 - 3. This way, even though you would detect something on the duplicates, you don't actually get to that point because the loop stops.
I added in the list of IF statements a condition to just un assign the "Bluetooth LE XINPUT compatible input device" as soon as it connects by using:

GML:
}
var gp_description = gamepad_get_description(global.Controller_Slot[i]);

else if gp_description == "Bluetooth LE XINPUT compatible input device" {
    show_debug_message("Disconnected Pad " + string(pad) + " from Player " + string(i));
    global.Controller_Slot[i] = noone;
}
It seems to work just fine as if it was detecting only 1 device like the Xbox One Controller. I tested with Multiplayer and it doesn't even assign it to the 2nd player anymore.
 

kburkhart84

Firehammer Games
I added in the list of IF statements a condition to just un assign the "Bluetooth LE XINPUT compatible input device" as soon as it connects by using:

GML:
}
var gp_description = gamepad_get_description(global.Controller_Slot[i]);

else if gp_description == "Bluetooth LE XINPUT compatible input device" {
    show_debug_message("Disconnected Pad " + string(pad) + " from Player " + string(i));
    global.Controller_Slot[i] = noone;
}
It seems to work just fine as if it was detecting only 1 device like the Xbox One Controller. I tested with Multiplayer and it doesn't even assign it to the 2nd player anymore.
So you are depending on that exact description....good luck when that doesn't match up. It wouldn't work with my hardware for example because I'm not using a bluetooth device. ALL XInput devices have the same duplication issue, not just the bluetooth ones.
 
So you are depending on that exact description....good luck when that doesn't match up. It wouldn't work with my hardware for example because I'm not using a bluetooth device. ALL XInput devices have the same duplication issue, not just the bluetooth ones.
While using Xbox Controllers with GameMaker, I have never experienced a duplicate controller issue. Not even with Direct Input Controllers. The Xbox Series Controller is the only Controller I have actually had issues with.

I have other ways of setting up mapping for other controllers. I just like to check for exact controllers when possible. But if the Controller is not recognized, it either gets a default mapping or the player can enter a custom mapping string using the SDL Gamepad Tool by General Arcade.

All of this has been working fine in my testing. The only issues was the Xbox Series Controller.
 

kburkhart84

Firehammer Games
While using Xbox Controllers with GameMaker, I have never experienced a duplicate controller issue
I have an XBOX 360 USB controller, and I certainly get the duplicate controller issue. I don't know if you are just doing something different this time around or what, but in general ALL XInput devices come up with duplicate DInput devices. I'm guessing exceptions might be software emulated ones(like I used to use for the PS3 controller). But hey, if it works for you, more power to you.
 
I've been personally testing controllers to make sure they work, perform well and have the correct mapping. So far I've been able to get most controller to work without having to install additional software. Except for the SDL Gamepad Tool by General Arcade to get the mapping. I don't use external software to connect controllers, because want controllers to be able to be recognized and connected without users needed to use external software.

The controllers I've personally tested are: PS4, PS5, Nintendo Switch Pro Controller (Afterglow), Nintendo Switch Pro Controller Wired, Nintendo Switch Right Joy-Con, Xbox One, Xbox One PDP Rock Candy Wired, Xbox One PDP Arctic White Wired, RetroBit Mega Man SNES Style Gamepad and Xbox Series X|S.

Out of all of these Controllers the only one that registers are two devices is the Xbox Series X|S Controller.
 

Simbiat

Member
I encountered similar issue, but I was getting
found gamepad 0 with GUID none description XInput STANDARD GAMEPAD
found gamepad 4 with GUID 030000005e040000130b000000000000 description Xbox Series Controller

in my debug console.
When connecting by wire I was only getting
found gamepad 0 with GUID none description XInput STANDARD GAMEPAD
Since I first thought that this is a GameMaker bug (well, not this, but something related), I had a ticket 208139 created for this and I shared a link to this thread there. Maybe they will be able to address this on the engine's side somehow.
 
Top