Search Unity

Joystick Input Weirdness

Discussion in 'Editor & General Support' started by Daz_Genetic, Jan 24, 2017.

  1. Daz_Genetic

    Daz_Genetic

    Joined:
    Sep 19, 2012
    Posts:
    1
    So this appears to be a Unity specific issue and I've been pulling my hair out about it.

    I have a FrSky Taranis X9D. It's an RC controller that acts as a Joystick when plugged into the computer. Shows up fine in the windows dialog for configuring the joystick. Each axis smoothly covers the entire width and everything looks perfectly calibrated.

    I have also fired up a couple of other non-unity games and everything continues to behave as expected. In games like Live For Speed, where the joystick configuration page display the joystick axes, you can visually see that each joystick axis smoothly covers the entire input range with no weirdness.

    Now in Unity, I get completely bizarre values from both Input.GetAxis and Input.GetAxisRaw.

    The first 50% of each axis movement returns a solid -1, or 1, depending on the axis. Then the other half the joystick throw returns a smooth value from 1 to -1. So only half of the joystick movement is working like the entire joystick and everything outside this range is returning some maximum value in one direction or the other.

    The controller is fully programmable and I have seen guides online for other Unity-based simulators to compensate for this behavior. However, when you do this, you break it for every other application that appears to read the joystick values correctly in the first place. This is exactly what Simulators like FPVFreerider have you do to make the Taranis work correctly, but it seems like there has to be a correct way of solving this problem. To get Unity to grab the joystick Input values that every other program seems to be able to read just fine.

    Why is Unity grabbing different joystick values than every other application? Is there some kind of script or addon for Unity to force it to read values through a standard windows interface?
     
    juanitogan likes this.
  2. DevLurkin

    DevLurkin

    Joined:
    Oct 4, 2014
    Posts:
    1
    Hey Daz, did you ever find a solution? I am having the exact same issue. Same transmitter too.
     
    caiquedm11 likes this.
  3. juanitogan

    juanitogan

    Joined:
    Aug 18, 2017
    Posts:
    27
    This appears to be the same problem I'm having with my Thrustmaster Firestorm Dual Power controller. Someone else complains about the same or a similar Thrustmaster controller here: https://forum.unity.com/threads/thrustmaster-joystick-input.222388/

    That thread offers a complicated solution that I haven't tried (I just grabbed another controller for now). My best guess was perhaps DirectInput vs XInput issues (due to the age of my controller) but your controller blows that guess out of the water considering how new it is.
     
    Last edited: Nov 16, 2017
  4. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Because Unity grabs the values from the HID input report directly which means they have to interpret the axis values manually. Most other games that support non-XInput devices use Direct Input. Direct Input reads and interprets the HID input report for you, and it also applies calibration you've set for the joystick in the Windows control panel. Unity's HID implementation does not handle all types of axes correctly. The reason Unity doesn't use Direct Input is that has been deprecated for roughly 13 years since XInput came out.

    While XInput was touted as a replacement for Direct Input, it simply is not. XInput supports a fixed number of buttons and axes based on the Xbox 360 Controller. It cannot handle any device that is not designed to conform to that standard, which means it only works with some PC gamepads, devices made for the Xbox 360, and some devices made for the Xbox One. I don't know of a single PC flight controller that is XInput-compatible. They all must be handled through either reading the HID report directly, Raw Input, or Direct Input.

    My input system Rewired gives you the option of using Raw Input or Direct Input combined with XInput to cover the biggest range of devices. It also has its own Raw Input implementation which can handle many axes that don't work correctly using Unity's system.
     
    Last edited: Nov 20, 2017
    juanitogan likes this.
  5. juanitogan

    juanitogan

    Joined:
    Aug 18, 2017
    Posts:
    27
    Thank you for clarifying that Unity doesn't use DirectInput. And, as far as I can tell based on how Unity responds to my Xbox 360 controller, it doesn't use XInput either. Not sure if you meant to indicate that or not. Anyhow, base on that, I would guess that Unity doesn't support either of these because of its cross-platform goals and not deprecation. On that note, I guess it is too much to ask of a game engine to support controllers at minimum level equivalent to SDL2 out of the box.

    Personally, even though Microsoft calls DirectInput "legacy" I wouldn't call it deprecated when there is no adequate replacement for it yet and new devices continue to be designed for it. It is also hard to imagine Microsoft winning a battle to force controller manufacturers and game designers to build and support more dual-USB controllers just to adapt to the more limited XInput. As far as flight controllers go, it's not hard to find the XInput ones by searching for "Xbox flight stick." These limit themselves to 4 to 6 axes when in XInput mode versus more axes in PC mode.

    Anyhow, beyond that interesting discussion, I'm currently in R&D mode of an 8-player multiplayer game that will likely need a package like yours. What I didn't see addressed on your pages, however, is whether or not your tools allow the two analog triggers on the Xbox 360 controller to be seen as separate axes or as both on one axis. MS says this controller has two axes on these triggers when read by XInput, and one when read by DirectInput. My Unity test with the Input library shows only one axis here and I would like to overcome that limitation in Unity. Can your package help with that? BTW, this tool http://www.generalarcade.com/gamepadtool/ for example, reads the triggers separately (because it sees an XInput controller) while MS's own Game Controllers tool sees one axis (because the MS tool favors DirectInput over XInput, I guess???).
     
  6. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Yes, it does support XInput. Based only all my testing, XInput devices are merged to their HID device. XInput is used to get the L/R Trigger values and HID is used for the rest. It would be impossible to get separate trigger values without using XInput. This act of merging the HID device to the XInput device is a big problem though because there is no way to reliably do this and the best they can do is guess which HID device goes to which XInput device. This is why the L/R triggers can get mixed up when you plug and unplug XInput devices, sometimes having the triggers on one device activate on the other.

    There's basically nothing that Direct Input can do that Raw Input / direct HID cannot. Direct Input is built on top of those technologies. Unity chose to implement direct HID and not Direct Input because Direct Input is deprecated and making it part of Unity would require that the end user install the Direct X runtime to use Unity.

    There is a lot of information on XInput here:
    http://guavaman.com/projects/rewired/docs/KnownIssues.html#xinput-device-name

    1. XInput is limited to 4 devices. There is no possible way to make 8 XInput devices have functioning separate L/R triggers.

    2. It is impossible to get separate L/R trigger values without using XInput or a driver that emulates it (in the case of Mac or Linux). The Windows HID driver returns both triggers as a single axis whether accessed by Direct Input, Raw Input, or direct HID. This is by design by Microsoft.

    3. Microsoft's Control Panel gamepad tool uses Direct Input only. It does not use XInput. In addition, setting calibration in this tool only affects Direct Input, not Raw Input, direct HID, or XInput.

    Unity has supported independent L/R triggers on XInput devices on Windows since probably some version of Unity 2.x. The HID unified axis is reported on Unity axis 3 and the separate XInput axes are reported on Unity axes 9 and 10. It is possible however to break the alignment of the HID and XInput devices by hot plugging leaving you with non-functional axes 9 and 10 or even having them activated by the wrong gamepad.
     
    juanitogan likes this.
  7. juanitogan

    juanitogan

    Joined:
    Aug 18, 2017
    Posts:
    27
    Whoa! Good point! I knew about the 4-device limitation of XInput but I hadn't considered _all_ the ramifications of that. Thank you for the intel, including the intel on your issues page. It sounds like if I want to target Windows as a platform for more than 4 players, I'm in for a world of support hurt. I'll have to design around that with perhaps two modes for Windows: XInput for 4 players, and non-X for 8 players with a different set of control options.

    Thanks for your help. I'll take a closer look at your package as I move forward.

    And, oh, I still can't get axes 9 and 10 to work with the 360 controller regardless of what I try. Even after a fresh boot and it testing fine in other tools. But I'll have to ignore that point for now as I see it could be due to all sorts of things (including Unity or Microsoft). Shocking to hear you can't get raw access to the individual L/R triggers. I didn't see that coming. Microsoft!
     
  8. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    You might try changing your Unity input manager axis "Joy Num" setting to use "Get Motion from All Joysticks" which will get the values for all possible devices simultaneously. This would show you if the values are actually there but are just not aligned to the right index.

    This is explained here:
    https://msdn.microsoft.com/en-us/library/windows/desktop/ee417014(v=vs.85).aspx

    The Xbox 360 controller is not a standard HID-compatible device. It cannot use the default HID driver on any platform and requires a special driver. Microsoft created a HID driver on Windows to make it appear as a HID device, and this driver is responsible for exposing the triggers as a single shared byte.
     
    juanitogan likes this.
  9. juanitogan

    juanitogan

    Joined:
    Aug 18, 2017
    Posts:
    27
    Thank you. When that suggestion didn't work it woke me up and I quickly found my mistake. I had forgot to uncheck "Invert" on my test input. Which, when I noticed that I was like "D'oh!" I'm sure these are only half axes and I cannot leave that checked.

    Yeah, I read that MSDN page a week ago. I found it clear about DirectInput vs XInput but I don't recall it addressing anything lower level like your material does. I'm fairly in tune to much of this, I just don't know it nearly as deeply as you. For example, I don't know the precise differences between what you are calling raw and HID input, but I also can't afford the time right now to learn all that myself. I have a rough idea of what HID is and what you are talking about there and will just leave the final expertise up to you. I am tempted to break into the Xbox 360 signals (perhaps using XBCD code as a guide) to look for a low-level solution but, again, no time for that right now -- especially since I have multiple control options to fall back to, when needed, per platform.
     
  10. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    They aren't half axes. Unity uses XInput for them which you can tell they do because you can press both triggers at the same time and it won't zero out both trigger values. I can't see why you wouldn't be able to invert these values.

    I am referring to using the Raw Input API vs the HID API.

    If you really want to do this to see if it's possible to support 8 controllers with separate triggers, save yourself the trouble and look at the Linux drivers. (I know the OSX driver can still only support 4 controllers, not sure about Linux.) It's likely to be very complicated because you have to deal with 360 wired, wireless, Xbox one (3 different revisions), Xbox One wireless dongle, Bluetooth version, etc. Each time a new one is released, the Linux drivers have to be updated to support it. Frequently, without updates, newer devices will cause the system to crash when plugged in, such as happens with the 3.5mm audio jack 2nd revision Xbox One controller on Linux distros with an older driver that doesn't support it. You will also need to maintain a giant list of Vendor Id / Product Id combos to add support for new generics that come out. I doubt you'd want to have to be managing either of these issues for your game.
     
    juanitogan likes this.
  11. juanitogan

    juanitogan

    Joined:
    Aug 18, 2017
    Posts:
    27
    Perhaps I spoke a bit too loosely. To me they are half axes when split because they move from 0 to 1 instead of -1 to 1. And, yes, they do invert fine and move from 0 to -1 when inverted. Before I had starting testing the 360 triggers, I had changed my code to respond only to positive values, which was another oversight on my part when I was testing the 360. But, such is the way of programming when building in multiple directions at once and the 360 behavior wasn't my highest priority.
     
  12. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Ahh, I see. Thanks for the clarification.
     
  13. Squall_Leonhart

    Squall_Leonhart

    Joined:
    Jun 13, 2013
    Posts:
    4
    This is a nonsensical response.

    Every version of DInput dll is included with the base install of windows, while the Xinput dll's may not be depending on Windows version used.

    Infact, its nonsensical further because the Dx runtime is required anyway when a game happens to use one of the D3DX compiler libraries which NONE are pre-included with any Windows version, (excluding a couple of files in 10 that are required by Dotnet 4.7 and pushed by Windows Update on 7 and 8)

    There has never been a valid reason for dropping DirectInput, and it all comes down to idiot politics by the unity platform developers choosing to drop an input method which is locked in (deprecated meaning no longer developed, not no longer functional) meaning no changes to test against, while Xinput and DirectHID introduce platform specific problems just because Microsoft 'fixed' something.

    Except work properly on all controllers.
    Because Raw Input and DirectHID definitely do not.
     
  14. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Don't judge Raw Input or Direct HID's capabilities by Unity's implementation. It's up to the implementer to parse the HID data and handle it correctly. Unity does not. Rewired's Raw Input implementation handles a ton of devices that simply don't work using Unity's implementation because the system was written to handle the HID data returned by these devices. For the most part, this is not a case-by-case issue and just simply accounting for all the HID value format possibilities defined by the standard.
     
  15. Squall_Leonhart

    Squall_Leonhart

    Joined:
    Jun 13, 2013
    Posts:
    4
    My judgement was on unity's base capability, which is lacking for what claims to be a cross platform engine.

    I've been pushing numerous devs to either get a custom input manager into their game or properly implement xinput support.

    Some of them have, but incorrectly, for example the developers of Oddworld New n Tasty have left the unity input manager receiving control inputs leading to misbehavior when the user has enabled the xinput check box because it continues to receive data directly from HID.
     
  16. prithiv

    prithiv

    Joined:
    Jul 3, 2014
    Posts:
    2
    Hi, There's a walk-around for this (even every older controllers that behaves like this)
    I got the same problem going around for two days. What i did was,
    use third-party software like JoyToKey to map joystick X & Y axis to Mouse X and Mouse Y and get the mouse inputs inside Unity.
    Hope this works. I know that this isn't the sufficient way but it works like a charm.
    Enjoy.