I have a simple problem and I can’t find any solutions.
I need to display glyphs for input actions depending on the last used device. Kinda classical.
BUT, I need to make the distinction between all kind of controllers. I won’t display the same glyphs if it’s a XBOX360 controller nor if it’s a PS4 controller. For the sake of this thread, let’s say we want to make different glyphs for : PS4/PS5/Stadia Controller/Joycon/Switch Pro/X360/XOne.
I would like to avoid using PlayerInput (but if it’s the only drawback, I think I can live with it)
It does not give me the level of precision I need (for instance, making the distinction between a 360 and a One controller). I can’t know if it’s a Stadia controller neither for instance. Relying on the type is not enough, especially when they can change depending on the platform you’re building your game on.
Depending on what exactly you want to do, Gamepad.current might suffice, if you want to get all state notifications ever then InputState.onChange will do, just don’t forget to remove the callback after you’re done, otherwise it will be called way too often.
Usually things like “I need to do figure out what is the device of recently joined player” are done via listening to a button press, with gamepads connected over bluetooth it’s often done as “press A to join”.
Then for identification purposes you could try using InputDeviceDescription.serial, but the current implementation is a bit spotty, partially because we rarely do have a serial, but also because we’re not exposing port connection hierarchy right now. In this thread 2 Arduino's Leonardo as joystick inputs, only one inputs it's axis. we covered some basis how it should work, hopefully will come around to make device identification more robust.
I want to be able to detect (at all time, not only in a “press A to join” menu) whenever the player change device.
I can’t use only Gamepad.current as the player might be using a Keyboard, or a Touchpad. I want him to be able to change device on the fly, and for the game to adapt the glyphs automatically.
Furthermore, InputDeviceDescription.serial is empty (I use a xbox series controller, wireless, on a windows editor)
@Bastienre4 as I mentioned we currently don’t have a great platform independent implementation for this, sorry about it, in the future we plan to revisit device identification and make it as uniform as possible.
In this particular case XInput itself doesn’t provide any information about gamepads. Instead it reports user id, up to 4 in total, from 0 to 3. This user id is stored in device description → capabilities → user index, which you can see on your screenshot.
More info Getting Started With XInput in Windows applications - Win32 apps | Microsoft Learn
For USB HID devices you should be able to get the serial in most cases, but not all devices report it.
USB port topology is currently not exposed.
If your case is only to get the latest type of a controller, maybe you can achieve that by listening to all state events, checking device id on them, and then checking with input system what is the type for that device id.
@Bastienre4 reading a bit in our code, we have InputSystem.GetDevice(Type type), try passing InputDevice type there and see if that does what you want.
Because reading the code:
public static InputDevice GetDevice(Type type)
{
InputDevice result = null;
var lastUpdateTime = -1.0;
foreach (var device in devices)
{
if (!type.IsInstanceOfType(device))
continue;
if (result == null || device.m_LastUpdateTimeInternal > lastUpdateTime)
{
result = device;
lastUpdateTime = result.m_LastUpdateTimeInternal;
}
}
return result;
}
It returns the last updated for the type, so passing the most generic type to it should work.
That would be “ok”, waiting for a better device identification (in order to display proper glyphs depending on the precise type of the controller).
It at least would solve one of the issues, getting the last used device.
One question though, does it take into account the “noisy” devices or not (I’ve heard that PS4 controller for instance is noisy due to the gyro sensors & all)?
Sorry m_LastUpdateTimeInternal is currently ignoring the noise flag. Device.MakeCurrent() is the only thing currently called when there is any non-noise activity on a device. The way how PlayerInput does it currently is hooking into InputSystem.OnEvent and for every event doing EnumerateChangedControls to see if anything has changed.
I don’t immediately see how would you solve this without writing almost exactly the same code as in InputUser, maybe you can leverage it to do what you need?
I wonder if it shouldn’t be added in the InputSystem. It seem kind of an mandatory feature to me, esp. on some platforms like Stadia who requires you to react to controller change. And having to rely on some complicated, heavy code copied from an other component doesn’t seem very robust. I know I’m not the only Unity customer having (a lot of) issues with this subject, maybe there’s something you guys can do on your side to help us?
TBH, I really like the philosophy of the InputSystem, but the struggle to work around those features I need will probably make me go back to Rewired.
@Bastienre4 I understand that this use case is a bit of pain right now, sorry about it.
Would you mind to explain a bit in more detail what exactly you’re trying to do so I can better figure out what feature/fix we need to make? I get that is “show graphics for last used device”, which implies you probably want to switch control schemes based on last used device? We have a somewhat conflicting feature requests here. As in this thread 2 Arduino's Leonardo as joystick inputs, only one inputs it's axis. the solution is not to use last active device, but rather figure out the connection hierarchy.
TBH, I just gave up and went back using Rewired.
I encountered a 100% crash while I was trying to develop the rebind menu, it was too much for me (Case 1379126)
I don’t think it’s conflicting, it may just be different approaches.
In my case, as it’s a single player game, I just want an easier way to detect the device the player is really using to display the exact glyphs to show (and depending on the actual device, it’s not the same (X360, XOne, XSeries, PS4, PS5, etc).