tl;dr: Unity (as of at least 4.5.2) has significant problems dealing with two or more Xbox 360 controllers on Windows, where they randomly may not work at all, or have non-functioning triggers, and/or have phantom clones. This is significant because it is the most common controller on the most common platform for many desktop gamers. There is no known workaround or reliable method for returning all connected controllers to a working state, except by trial and error.
Update
The bugginess turns out to be due to a conflagration of several issues. As of Unity 4.6.3 and the 4.6.2p2 patch, two critical fixes have been made by Unity to address part of the problem:
- Windows Standalone: Adding/removing game controllers should be detected more reliably now.
- Windows Standalone: Fallback to XInput 1.0 when XInput 1.3 is not installed on the system.
Another critical fix was added in Unity 4.6.3p1 and 5.0.0p1:
- Input: Changed Input.GetJoystickNames() on Windows to always match names to joystick numbers, similar to most other platforms.
I believe there may be a few more issues to deal with, but it should be somewhat more reliable now.
Context
My project, InControl, has been an increasingly popular solution for cross-platform controller support in Unity.
Recently, I started receiving scattered bug reports about strange controller behavior on Windows. It’s been surprisingly difficult to get details, with some users never responding to requests for more information, or replying that the problem has inexplicably solved itself.
Reports covered a range of controllers, with the general flavor being controls not working, or working incorrectly, particularly triggers. Over time, the Xbox 360 controller has been the common denominator. Finally, one user responded with some specifics: two wired Xbox 360 controllers, on Windows, occasionally not working at all or the triggers not working properly.
An brief note on the Xbox 360 controller: Microsoft originally designed the triggers to work on a combined axis, with the left trigger adding 0..-1 to the axis and the right trigger 0..1. The value of the axis is the sum of the two trigger values. In Unity on Windows, this axis happens to be axis 2. Recently, support has (somehow) been added to Unity for splitting the triggers properly on axes 8 and 9.
As I experimented, it’s been relatively easy to reproduce, although it takes some persistence.
Results
With at least two Xbox 360 controllers connected, and launching Unity or a pre-built player on a freshly booted system, things usually work fine. If any of the controllers are attached and detached a few times, either while the app is running or before launch, things get a bit crazy. I found at least four states you can end up in randomly:
- Everything works perfectly.
- The controllers are recognized by Unity, and all controls work with the exception of the independent trigger axes (8 and 9). These are not to be confused with the combined trigger axis 2, which does continue work in this state.
- Both devices are recognized by Unity, but one or both devices do not report input.
- A "phantom" third device appears, which also receives input (so two joysticks in Unity are receiving the input from the same physical device, although one of them has the independent trigger axes working, while the other does not). This state is very rare.
The problem state will usually persist indefinitely through restarting Unity (or relaunching a built player), although, at least once I observed a controller going from state 3 to state 2 after relaunching Unity.
Once one or more devices are unplugged and replugged, it goes to a random state in the list again.
Often a broken state may be accompanied by one of the Xbox 360 controller player lights being “incorrect”. For instance, two controllers connected and they have lights 2 and 3 respectively. I’m not certain if Microsoft guarantees that two attached controllers will always occupy positions 1 and 2.
I should point out that even while in a broken state in Unity, input still works correctly for both controllers with other applications. For example, using the XInput API with something like XInput.NET, or opening the controller properties in Windows Devices and Printers and testing the inputs there. The devices are still fully functional as far as Windows is concerned.
Thoughts
There seems to be no reliable course of action to get the devices back into a proper state, even plugging them all out, closing Unity, plugging them all back in one at a time slowly, and relaunching Unity, does not always seem to work. Rebooting may be the most reliable option, but I have not tested this extensively (yet).
It is possible this bug manifests with other controllers too, as other controllers have been mentioned in bug reports I have received, but since at least one Xbox 360 controller has always been involved in every case, that issue needs to be resolved before any further assumptions can be made.
The Xbox 360 controller is the “go-to” device for most desktop gamers, and Windows is their platform of choice, so this is a fairly serious issue. I have submitted a bug report to Unity and Unity QA has been quick to respond. Hopefully, it can be resolved soon in a patch update.
A possible workaround in the short term, is turning on InControl’s XInput support, however, since the Xbox 360 controllers are still picked up and processed by Unity they may very well affect, and break other kinds of attached controllers.
I will update the status message at the top of this post as things progress.
(For some wild speculation on why the bug may be happening, read this follow up post.)