Unity API Specifics


Auto-Detect the Controller

In Unity, it is easy to detect if a controller is connected. A call to Input.GetJoystickNames() will return a String list of connected controller names. If the list has non-empty entries, you have at least one connected controller.

DPAD and System Buttons

Referring to either Unity controller mentioned previously, in The Middle Buttons section’s notes for the Left Most button, using the GetKey functions to check for Keycode.Escape usually means you are checking for the Android BACK key. Notice that none of the GetKey functions, or their input, allow for indication of a particular controller. So any controller pushing BACK will return true from these functions. This is not the only case where this happens.

In the table below, you will see other cases where you must use GetKey functions. In the cases where a joystick button is also emitted, it is highly recommended that you use the button, which is also listed in the Unity controller charts shown previously; nothing is contradicted. It is only listed here for reference, in case you are checking for both the key and button (i.e. using Button11 and Keycode.Pause).

Android Keycode
(from controller)
Unity Keycode Unity Button
(v4.3 and later)
Notes
KEYCODE_BACKKeycode.Escape  
KEYCODE_MENUKeycode.Menu  
KEYCODE_SELECTKeycode.PauseButton11Both values emitted.
KEYCODE_STARTKeycode.ReturnButton10Both values emitted.
KEYCODE_DPAD_UPKeycode.UpArrow Consider adding these in single controller games in addition to the normal check for Axis5/6, see The DPAD from the Unity controller charts. Some Mini-Controllers and Remotes only emit DPAD; see Android TV and Micro-Consoles.
KEYCODE_DPAD_DOWNKeycode.DownArrow 
KEYCODE_DPAD_LEFTKeycode.LeftArrow 
KEYCODE_DPAD_RIGHTKeycode.RightArrow 
KEYCODE_BUTTON_L1Keycode.LeftShiftButton4Both values emitted.
KEYCODE_BUTTON_R1Keycode.RightShiftButton5Both values emitted.

Handling Controller Disconnects

In Unity v4.5 and later, controller disconnects are much improved. The next section describes handling disconnects when using v4.5 and later. However, it may help to finish reading this section, so a contrast between both versions can be made. The following is for Unity pre-v4.5.

Unfortunately, Unity doesn’t have all the APIs necessary to handle disconnects gracefully. A developer’s sole way of detecting a controller is using Input.GetJoystickNames(). An application also does not get a notification that a controller has connected or disconnected. Handling these situations will take some thoughtfulness and reluctant acceptance.

When the application launches, all controllers that have ever connected will be contained in the joystick names list. This holds true whether they are connected or not, the controller name will remain in the list. However, there is an exception to this, if a controller that is being connected is the same model as a controller (or controllers) that were previously connected but are now disconnected, it will take the place of the first disconnected controller of that model.

For instance, consider an Android device with a USB hub connected to it. Connected to the hub are two controllers which are the same model. We’ll call those Xcontroller #1, plugged in first, and Xcontroller #2. Xcontroller #1 is first in the joystick names list, Xcontroller #2 is second. A couple of scenarios which will outline the problem:

The problem with this controller swapping, where Xcontroller #2 took the place of Xcontroller #1, is that the player who was on controller #2 is now controlling player #1’s character. If controller #1 reconnects, it will controller player #2’s character. Order of reconnection matters; there is no easy way to avoid this in Unity today.

There are several other scenarios that can be run through, but they all should follow the same rule: if a controller that is being connected is the same model as a controller (or controllers) that were previously connected but are now disconnected, it will take the place of the first disconnected controller of that model.

A couple of options a developer can consider:

  1. Educate the user on disconnects, either in the application or on the application’s download page. One good place would be when your application displays a controller map on the screen.
  2. Use a game-specific heuristic to decide when a controller is disconnected, and pause the application asking the user(s) to connect their controllers in player order.

There is currently no elegant solution in Unity version previous to v4.5.

Handling Controller Disconnects (Unity v4.5 or greater)

As stated in the previous section, a developer’s sole way of detecting a controller is using Input.GetJoystickNames(). An application also does not get a specific notification that a controller has connected or disconnected. However, unlike Unity versions previous to v4.5, the joystick names list entry does get cleared of a joystick when it disconnects. This will be the mechanism that the developer uses to query for disconnects.

Keep in mind that a developer still needs to manage what joystick name entry goes with which player. To illustrate this need, a similar scenario from the previous section will be used below.

Consider an Android device with a USB hub connected to it. Connected to the hub are three controllers, two of which are the same model. We’ll call those Xcontroller #1, plugged in first, Ycontroller #1, and then Xcontroller #2. Xcontroller #1 is first in the joystick names list, Ycontroller #1 is second, and Xcontroller #2 is third.

If Xcontroller #1 is disconnected, its name is removed from names list. The list will still have a length of 3, except the first entry will be empty. Then Xcontroller #2 is disconnected. The list still has a length of 3, except the first and third entries are empty. Now, Xcontroller #2 is reconnected, it will now occupy the first entry. Two items to notice: one, joystick list length remains the same even after disconnects, and two, Xcontroller #2 is now the first entry instead of the third.

Continuing with this scenario, disconnect the Ycontroller #1. The list contains only the Xcontroller #2 in the first entry and the next two entries are empty. Reconnect Xcontroller #1. One might expect it to occupy the next entry in the list, the second entry. However, it occupies the third entry, which makes the list have an Xcontroller in the first and third entries. A reconnected controller will occupy the first entry of any previously-connected but now disconnected controller if they are the same model, otherwise it will take the first empty entry that was never occupied by any controller. While this idiosyncrasy shouldn’t matter to a disconnection handling algorithm, it is important to know since you may consider this a bug.

A typical disconnect algorithm would poll the joystick names list every so often and wait for a cleared name, indicating a disconnect. Once a disconnect is signaled, the application pauses and, in single joystick applications, just waits for input again. It shouldn’t care which joystick it comes from. In multi-joystick applications, an application, once it notices a new joystick, needs a UI that can ask the users which joystick goes to which player. If there is only one disconnect, it could be implied that any new joystick should be attached to the only player without one. A typical UI has a metaphorical grid pattern where the joysticks are the rows and the players are the columns. Then each user moves their joystick icon down the row to the proper player column and locks it in. Once everyone has done that, the application can continue.

Handling Multiple Controllers

A call to Input.GetJoystickNames() will return a String list of connected controller names. This is also a list in which each joystick name’s index is the same number used to identify the controller in the Input Manager. Not using this index and selecting the options that concatenate all controller inputs, Get Motion for all Joysticks for Joy Num on axes, or joystick button n for a Positive Button, there is no way to tell what input came from what controller. So it is important to setup the Input Manager correctly.

To setup the manager correctly, every controller, up to the amount of controllers you support, must use its index — abridged Input Manager entry examples below. A special note in Unity pre-v4.3: because of how the triggers on a controller must be handled, a developer should define at least two controllers — see the Unity pre-v4.3 section below.

NameJoystick1Button0Joystick2Button0 Joystick3Button0
Positive Button

joystick 1 button 0

joystick 2 button 0joystick 3 button 0
TypeKey or Mouse Button
Key or Mouse ButtonKey or Mouse Button

NameJoystick1AxisXJoystick2AxisXJoystick3AxisX
TypeJoystick Axis
Joystick AxisJoystick Axis
AxisX axisX axisX axis
Joy Num
Joystick 1Joystick 2Joystick 3

A controller name can be tied to its index. A developer, through their application design, can now tie the index or name to a player. Using the index will allow the developer to differentiate between controllers. To highlight the point, consider this simple function:

function GetButton0Status(nControllerIndex:int) : float {
var flValue:float = 0.0;
flValue = Input.GetAxis(“Joystick” + nControllerIndex + “Button0”);
return flValue;
}

Unity v4.3 and Later

At the time of this writing, version v4.5.3 was the latest, which would not change any of the information below. Keep the “time of this writing” in mind when evaluating new Unity updates. Unless the input APIs or underlying frameworks change considerably, we believe the information below to be useful.

Handling the Triggers

If you are familiar with the complexity needed to handle the triggers in previous versions of Unity (pre-v4.3) to meet the specification, Unity v4.3 has resolved that. Even so, triggers still take some care to implement.

Please, re-read The Bumpers and Triggers section of the Unity v4.3 and later specification. The implementation is different than other axes, but should be trivial.

Handling Controllers in Single Player Games

In older versions of Unity, we recommended that developers define at least two controllers. This was for the scenario in which two controllers might be attached to a device, but only one is being used. Think of a SHIELD connected to a TV with a Bluetooth controller attached. It would seem logical not to care which controller an input came from in a single player scenario. However, in Unity versions previous to v4.3, some controllers would output transposed trigger values — controller group A would output 7th Axis/8th Axis for LT and RT respectively, and controller group B would output 8th Axis/7th Axis.

Thankfully, developers don’t need to consider this anymore. Couple that with wide adoption of the specification; in general, it is our recommendation that developers setup the Input Manager where all inputs are concatenated. For example, use Get Motion for all Joysticks for Joy Num on axes, and joystick button n for a Positive Button on buttons.

Changes Needed for Input Manager

The Unity IDE only allows a limited number of axes to be defined. To fully implement the specification, more axes are needed than the IDE drop-down will allow. To address this, assets need to be saved in text mode. Forcing assets to be saved as text is easy; open the IDE, then go to Edit > Project Settings > Editor.

In the Editor Settings dialog, switch the Asset Serialization Mode to Force Text.

Before you start editing, it is recommended that you set up one controller as much as possible through the IDE. This will allow you the template needed to add more axes or buttons when editing.

Edit the InputManager.asset in the ProjectSettings folder of your Scene. Use the previously set up controller entries as templates to create all the axes or buttons needed. Note that if you look at those numbered axes that are not support in the IDE drop down, it will show up as blank in the Joy Num entry. This is expected.

Unity Pre-v4.3

Handling Multiple Connected Controllers in Single Player Games

In a single player game, the reason for handling multiple connected controllers isn’t so obvious on the surface. However, consider the micro-console, which may have several controllers connected at any given time, or a SHIELD connected to a TV and a Bluetooth controller. In these scenarios, it would be impossible for an application using Get Motion for all Joysticks to tell from which of the joysticks an input came.

One important case where a developer needs to tell which controller an input came from is described in Handling the Triggers below. Not handling this case will seriously decrease the amount of controllers your game will support “out of the box.” We will forgo a sample in this section, as handling multiple controllers folds right into handling the triggers.

Handling the Triggers

The controller specification in Unity, when it comes to the triggers, involves some thought and handling. The specification shows that some controllers will give inputs of 7th Axis/8th Axis for LT and RT respectively; while other controllers will give the reverse. If this reversing doesn’t matter to your application, this section can be safely skipped.

There are a few ways to handle this situation. Two will be described below and should give a developer a decent foundation on developing a solution specific to their application, even in multiplayer situations. By necessity, the solutions below will also handle multiple connected controllers. It is recommended an application handle at least one extra controller connected, for a total of two in a single controller application.

These solutions will use some short-hand and pseudo-code, especially when it comes to the Input Manager, without hurting the clarity. The scenario is a single player game in which the LT is “use scope” and RT is “fire.”

Setup the Input Manager

NameJoyAllFire Joy1Fire Joy2Fire
TypeJoystick AxisJoystick AxisJoystick Axis
Axis8th Axis8th Axis8th Axis
Joy NumGet Motion from all JoysticksJoystick 1Joystick 2

Helper Function for Solutions

function IsTriggerFlipped (strController : String) : boolean {
// The controllers below are known to NOT need the triggers
// flipped from what we’ve defined in the InputManager. There
// are less of these to check against.
if (strController.StartsWith("NVIDIA Corporation NVIDIA Controller v01"))
return false;
// These are true in 4.3 and modern NVIDIA devices.
if (strController == "Microsoft X-Box 360 pad") return false;
if (strController == "Generic X-Box pad") return false;
if (strController == "OnLive Wireless Controller") return false;
return true;
}

 

Solution Idea 1
// Handles 2 controllers well.  Any controller after the 2nd
// controller will be considered non-flipped. Extending this
// to n-controllers is trivial.
var flScope:float = Input.GetAxis("JoyAllScope");
var flFire:float = Input.GetAxis("JoyAllFire");
var nUsingJoyNum:int = -1;
if (flFire > AXIS_FIRE_THRESHOLD) {
if (Input.GetAxis("Joy1Fire") == flFire) nUsingJoyNum = 0;
if (Input.GetAxis("Joy2Fire") == flFire) nUsingJoyNum = 1;
}
if ((flScope > AXIS_SCOPE_THRESHOLD) && (nUsingJoyNum < 0)) {
if (Input.GetAxis("Joy1Scope") == flScope) nUsingJoyNum = 0;
if (Input.GetAxis("Joy2Scope") == flScope) nUsingJoyNum = 1;
}
if (nUsingJoyNum >= 0) {
if (IsTriggerFlipped(Input.GetJoystickNames()[nUsingJoyNum])) {
var flTemp:float = flScope;
flScope = flFire;
flFire = flTemp;
}
}
Solution Idea 2
// Will handle any number of controllers that are connected. The
// part that needs some care is deciding when a particular
// controller is _the_ controller.
var flFire:float = 0.0f;
var flScope:float = 0.0f;
var nControllerNdx:int = 0;
var strControllerTable:String[] = Input.GetJoystickNames();
while (nControllerNdx < strControllerTable.length) {
if (IsTriggerFlipped(Input.GetJoystickNames()[nControllerNdx])) {
flScope = Input.GetAxis("Joy" + nControllerNdx + "Fire");
flFire = Input.GetAxis("Joy" + nControllerNdx + "Scope");
} else {
flFire = Input.GetAxis("Joy" + nControllerNdx + "Fire");
flScope = Input.GetAxis("Joy" + nControllerNdx + "Scope");
}
// Insert heuristic on what controller is being used.
if ((flFire > AXIS_FIRE_THRESHOLD) || (flScope > AXIS_SCOPE_THRESHOLD))
break;
nControllerNdx++;
}

 

 

 


NVIDIA® GameWorks™ Documentation Rev. 1.0.200605 ©2014-2020. NVIDIA Corporation. All Rights Reserved.