Joystick detection and direct axis detection

I’m writing an Input Manager of my own to replace Unity’s that will allow my players to customize their controls in-game as well as allow me more fine grained control of how they customize things. I’ve got it working pretty well, but ran in to some problems because I can’t find any way to access input functions at a lower level than through the basic stuff available in Input.

1.) Joysticks are not ever detected when plugged in while game is running. (Tested in editor and build.) Is there any way to re-poll for joysticks while the player is running in case they a) forget to plug a controller in before or b) remove a controller mid game or c) add a 2nd controller in mid game to join in.

2.) There seems to be no way to get an axis directly without first setting it up in Unity’s Input Manager. I can access all keyboard, joystick, and mouse buttons through Input.GetKey, but there’s no equivalent for axes as Input.GetAxis just takes a string which matches whatever axis you set up in Input Manager.

3.) There’s very little available for managing joysticks. The only way I can even detect how many controllers are connected is with Input.GetJoystickNames. I’m wondering if there are any undocumented features for input management that I might get access to to help me get the most out of input.

Can anyone give me guidance on how to use reflection to find out if there are any undocumented methods/properties in Input?

Well, you can find tool that is named ILSpy and watch source code of .NET libraries (still I don’t know if I am allowed to say this on official forum :slight_smile: ) .If libraries are not obfuscated you can see some useful things but I strongly don’t recomend you to use undocumented features as they can disappear in next version or even work improperly.

UPDATE: ufo_driver, ILSpy looks like it’s what I needed. Thanks again!.
UPDATE2: Well there’s a whole lot to see in there, but I don’t see any way to get more control over the controllers. :frowning:

Thanks for the tip! I’ll see what I can find using that. I realize using undocumented features isn’t the greatest idea, but I would seriously like to find a way to make Unity re-poll the controllers when hotplugged. This is a big drawback IMO, and I seriously doubt the Xbox 360 and PS3 versions would have this same problem as all games on those systems can detect controller removal. It seems the PC version should be able to do that somehow. It’s an even bigger issue for wireless controllers.

Since I’m nearing the completion of my game, I don’t think worrying about future support for undocumented functions is really a big deal for me. (It’s a standalone ver, not webplayer so I shouldn’t need to worry about the player getting updated either.)

My approach to reflection was going like this:

var refl : Reflector = new Reflector();
var propertyInfo : System.Reflection.PropertyInfo[] =  Reflector.GetProperties(System.Reflection.BindingFlags.Default);

class Reflector extends Input implements System.Reflection.IReflect {
}

However I get the error “Cannot extend final type ‘UnityEngine.Input’.”

I’ve run into another problem… I’ve got my entire input manager built, but I’m having trouble identifying joysticks by id. The only function I’ve found for determining anything about connected joysticks is Input.GetJoystickNames which returns a string of joysticks connected since run. I was using this returned string to get names of controllers for the config screen to let users choose which player is using which controller. I also use this name list to determine which joysticks are in which positions (joy 0 - joy 3) and map to players accordingly. (I’m also planning on having default joystick config profiles based on the joystick name so I can set up decent defaults for more popular game controllers.)

PROBLEM: My entire house of cards just came falling down because I’ve determined the order of joysticks returned by Input.GetJoystickName DOES NOT relate to the order the joysticks are handled by unity. For example, a joystick in the returned name array in position [0] does not always equal the unity mapped Joystick1 (Input.GetKey(Joystick1Button0)). SOMETIMES it does, but sometimes it doesn’t. (Try connecting 3 or 4 different model controllers, doing a Input.GetJoystickNames to see your list of controllers, then poll all the joysticks while pressing buttons on various controllers and see how the mapping doesn’t always match.)

Is there any other way to determine what controllers are connected and what their respective unity joystick number is?

Example of how joystick names do not always match joystick ids:

// Slap this code onto an object in the scene then press buttons
// I recommend you test with 3-4 controllers (different models) for best effect
function Awake() {
	var names : String[] = Input.GetJoystickNames();
	Debug.Log("Connected Joysticks:");
	for(var i : int = 0; i < names.length; i++) {
		Debug.Log("Joystick" + (i + 1) + " = " + names[i]);
	}
}

function Update() {
	DebugLogJoystickButtonPresses();
}

private function DebugLogJoystickButtonPresses() : void {
	var joyNum : int = 1; // start at 1 because unity calls them joystick 1 - 4
	var buttonNum : int = 0;
	var keyCode : int = 350; // start at joy 1 keycode
	
	// log button presses on 3 joysticks (20 button inputs per joystick)
		// NOTE THAT joystick 4 is not supported via keycodes for some reason, so only polling 1-3
	for(var i : int = 0; i < 60; i++) {
		
		// Log any key press
		if(Input.GetKeyDown(keyCode+i)) Debug.Log("Pressed! Joystick " + joyNum + " Button " + buttonNum + " @ " + Time.time);
		
		buttonNum++; // Increment
		
		// Reset button count when we get to last joy button
		if(buttonNum == 20) {
			buttonNum = 0;
			joyNum++; // next joystick
		}
	}
}

Unity Script Reference - Input.GetJoystickNames states:

Because the joystick id does not always map to the corresponding entry in the GetJoystickNames array, this statement in the Unity docs appears to be incorrect. I can see no way to use the names returned by this array as there’s no way to relate them to an individual controller.

The above test was done with all controllers connected to the system from program start, nothing removed. Therefore I’m confident it’s a bug and I’ve reported it. However, even if that bug is fixed in the future, there will still be a case of id mismatching if a controller is ever removed while the program is running. Ex: 3 controllers connected, controller id 1 is unplugged. Now GetJoystickNames() returns a 2 element array, 0 = id 0, 1 = id 2. Again, no way to associate a name with a joystick. There MUST be a way to access joysticks by id, THEN get name from that.

Update: Controller order seems to change depending on which USB controller the joysticks are plugged into. (In the off chance one of the dev team reads this, that may be somewhere to start testing.)

All these limitations with the Input class are seriously messing up my plans to have a good input experience for multiple players on one system.

Another example of the problems with Unity’s input handling:
I mentioned in my posts above that I was searching for a way to hot-plug controllers during the game and never found any way to do it. Here’s a real-world scenario that WILL cause big headaches for players, even in a single player game – Player is using Xbox 360 wireless controller or another wireless controller. Player pauses game and gets up to do something for 20 minutes. Controller shuts off. Unity drops controller from list. Player comes back and reconnects. Unity ignores the new controller. Player cannot control game anymore and is forced to quit with mouse/keyboard and re-run the game.

I’ve been working with unity for almost 2 years now and have found it to be all around great, but the Input class is just sorely lacking.

1 Like

guavaman, I share your frustration with the way Unity handles joystick inputs. Unfortunately, I don’t have a solution, only solidarity. Here is a thread I just posted to describe the problems I am running into.

How do I map joystick buttons beyond 20 and axes beyond 8?

Aside from the issues with Input (and source control management) I am the biggest Unity fanboy on the planet. Let’s hope the Unity Devs take notice and fix their insufficient code!

Sad. I was hoping 3.5 would have a fix for it but I didn’t see any Input changes in the release notes. Vote for them to address multiple joystick problems here: http://feedback.unity3d.com/forums/15792-unity/suggestions/2151101-fix-multiple-joystick-support-windows-

I posted my support on the feedback page you linked to. So sad, I gave similar feedback when the current version was 2.x. Does anyone at Unity ever listen? I would at least appreciate an explanation as to why this is difficult or impossible for them to do. If there are good reasons why this can’t be done I would be sympathetic.

I think you need to add your votes. Click the vote button near the top. It will allow you to add 1 or more votes depending on how many you have left. (Of course, if you want to add a new topic about more axes/buttons and use your votes there instead, you should do that. EDIT: There’s one already:http://feedback.unity3d.com/forums/15792-unity/suggestions/940687-increase-joystick-button-limit but it doesn’t mention Axes)

I don’t feel like this is a difficult problem at all to solve. I already sent them a detailed bug report and outlined a simple to implement solution that wouldn’t take a lot of time. In my view, the devs are just too busy adding the latest, greatest whiz-bang features and systems that everyone wants and have no time to go back and fix small bugs that most of their users don’t care about. Lets face it, how many PC gamers actually use controllers compared to those that use mouse/keyboard? It’s sad, but you can see by the paltry 19 votes for the joystick fix that not a lot of people use multiple joysticks on the PC. New feature requests far outshadow bug fixes.

I would appreciate it if they’d at least acknowledge the problem in an email or something after my thorough bug report. Looks like PC controller support is going to be broken past my release date. I guess I’ll have to include some kind of controller disconnection disclaimer telling players that the engine’s support for controllers is broken and if you unplug a controller or your wireless controller times out, you MUST quit the game and restart for the new changes to take effect. As for your problem with not enough buttons/axes, I don’t see any solution within Unity. It would be a big headache, but maybe you can completely replace the Input system using some kind of plugin DLL. (Not sure of the details but I have seen some Xinput project where you could add a DLL and get access to inputs outside of Unity’s handling. I may do some research in this area later as I’ve kind of moved on from controllers for now.)

And this is probably the real reason why the fixes are not making their way to the top of the list.

PC driving and flying games are about the only games I can think of off the top of my head that people might be included to buy specialized hardware for. Flying games are pretty much dead - and only die hard racing monkeys actually buy a wheel for their PC to play already established games, like iRacing vesus some kind of arcade style game, like the NFS series, which plays perfectly fine with a keyboard.

I’ve been dealing with the exact issue as of late. I’ve been trying to figure out a possible solution, and it seems that you can use XInputDotNet instead of the built-in Unity InputManager which I can attest fixes the issue. Problem with that, it uses DirectX which means Windows only.’

There’s also XboxCtrlrInput which attempts to create a more multi-platform solution, using XInputDotNet on Windows and seemingly falling back to Unity’s built-in InputManager for all other platforms.

Sad that this issue has remained in Unity for so long (well over two years, I’m sure!)

I’m saddened and a bit suprised (though I shouldn’t be) to hear that this issue is still unresolved. See this post from a Unity staff member over a year ago. I hadn’t checked back on this issue myself, but assuming you’re using 4.3, I guess we’re never going to see working controllers in Unity.

I really don’t like the idea of resorting to external plugins to solve the problem because like you said its not cross-platform. That means essentially you have to find external solutions and rewrite your controller management code for every platform you intend to publish on. That said, thanks for posting your workaround. I will probably have to dig into this because I simply can’t wait forever.

Unity really does not support game controllers. That’s about the size of it.

Same issues here. Saying “not many people use joysticks” is not an excuse for Unity to ignore these bizarre problems. Though I’m not sure they’ve ever given that as an excuse. We’ve just been ignored. If you are making a flight sim or space sim like I am, then joysticks and game controllers are a standard requirement. Modern joysticks and controllers have a wide variety of axes and buttons so the limitations of 20 buttons and a handful of axes is just foolish.

I see people have been discussing this issue for up to 3 years and nothing has changed. I might go look at Unreal or other engines now as this is a showstopper/dealbreaking issue for any flightsim developer.

Looking up this exact issue and pretty sad to see there’s no proper solution.

I have a game where it’s highly encouraged to play with a controller and when people find that out they are forced to restart it in order to have the game recognize the controller (web game).

This really sucks =\

Look into InControl, InControl: Introduction - Gallant Games. It’s a fantastic input library for Unity that abstracts away a lot of the issues with InputManager and provides numerous out-of-the-box support for a lot of controllers.

However, there’s not going to be a guaranteed way to ensure controller order unless you use XInput. This is a Windows driver issue more than anything, so I don’t think Unity can be blamed entirely (if at all).

So to get around this, if you end up using InControl, you’ll need to create some type of character selection screen and listen to all of the attached controllers. When a player selects a character, capture reference to the InputDevice (an InControl class that represents controller state) that made the selection and use that to represent the player going forward.

I’m currently working on a complete controller input system to replace Unity’s. I’m hoping to release it within the next week or two. But it has a number of features that will make working with joysticks (and other controllers) far better than Unity’s input system or any plugin that wraps Unity’s system. For starters, it will fully support hot-plugging on Windows, Windows Store, and OSX games (Linux and Android planned if there’s enough interest.) However, unfortunately, it is not possible to support hot-plugging in web players. Apart from hot plugging, it features a player-centric input system (player.GetAxis(“Walk”) gets all the player’s joystick, mouse, and keyboard inputs that have the “Walk” action mapped), auto re-assignment of controllers to players on controller disconnect/reconnect (if hot-plugging is supported on that platform), connect/disconnect events, frame-rate independent input (get input in Update or Fixed Update), customizable (and saveable) controller mappings, multiple mapping layouts per joystick, joystick calibration, multiple controllers per player, an editor GUI for creating actions and controller/keyboard/mouse maps, named buttons and controller elements per-joystick (for help messages and config screens), and much more. In addition, it does not abstract all controllers into a gamepad-style layout, so it will work with any controller type. However, to save time and effort, you can map a controller template such as Dual Axis Gamepad if you don’t feel like configuring all the supported controllers for your game and any controller that uses that template will work.

It’s not a Windows driver issue. I’ve solved the problem on both Windows and OSX. Unity hasn’t touched input in probably 8 years. It was just half implemented and forgotten. But I did see in another thread that they will be revamping input for some upcoming 5.x release, though not the initial release.

Could you explain this further? Everything I’ve ever read has always faulted the actual drivers and Microsoft, so I’m curious as to how you solved the 360 gamepad numbering issue.

XInput numbers the pads itself, as you know. So if you choose to use XInput (my prog has that option) for 360 pads, the numbers will be stable.

For other devices (or if you disable XInput), I’m using DirectInput. While the hardware ids can change occasionally on Windows when disconnecting and reconnecting, for the most part they stay fixed for the duration of the Windows session unless forced out of place by another device that had the id before it. Anyway, I remap the controller ids based on identifying information from the controller and map that back to a player. On connect, the device is assigned to the last player to own that controller (if you choose to use auto-reassignment). There is still the possibility of mix up if multiple identical controllers are used, but its minimized because of identifying information which usually stays fixed as long as the controller remains attached. So as long as one controller is removed then attached at a time and all of them aren’t removed together, everything should be fine. And if they do remove all of them together, they’ll just be reassigned to players as intelligently as possible. Even in the worst case, the identical controllers could be crossed, but it would be an easy matter for players to go into the option screen and switch controllers back. This issue is better on OSX because you can get more USB information than through DirectInput to keep the controller id in place. I may try adding a lower level layer in Widows to try to get even more hardware data on the device to make it more solid, but that will wait until after my initial release.

In my system, you will be getting input from the Player 99% of the time instead of controllers directly (you can, but there’s no real benefit and you lose out on all the goodies of player-based action mapping by hitting the controller directly). So you don’t even have to care whether a controller is at the same id as long as it’s mapped back to the player properly.

By the way, actions are player-based as well. So any controllers assigned to that player can return input for the action in question. You don’t have to create duplicate actions for multiple players anymore. All of this works for keyboard mapping as well – the keyboard can be partially mapped to as many players as you want, and will return input to the player for the actions being queried.

Any updates on your input manager replacement? I’ve recently ran in to a situation very similar to yours, and find it kind of silly that Unity can’t accurately determine which controllers are which. A solution would be much appreciated

Hi Terabyte. I’m polishing up the last bits and will have it out very soon. All that’s left to do is some testing, documentation, demos, and a website. Probably a few more days. I’m a bit behind my originally planned release date because I ended up expanding the scope a bit and added a number of goodies. Exciting! :slight_smile: