Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Xbox One UWP Controller Input mapping?

Discussion in 'Windows' started by slander36, May 26, 2016.

  1. slander36

    slander36

    Joined:
    May 26, 2016
    Posts:
    5
    I'm trying to build a project in VS2015 for Xbox One using the UWP on Xbox program. I've gotten basically everything working but the controller.

    I've used a Wireless Xbox One controller plugged in via micro-usb on Local Machine (desktop), which works in the Unity preview, but not after building to UWP. Wired Xbox360 controller works on Local Machine after building, however, so the UWP app is receiving some sort of input. Same goes for building Standalone: Xbox360 controller works fine, microusb Wireless Xbox One isn't detected.

    Is there some reason why the controller would work in the Unity preview but not after building for UWP via VS2015? I've tried searching around for hours and can't find anything about this.
     
  2. matt33315

    matt33315

    Joined:
    Mar 28, 2014
    Posts:
    94
  3. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,608
    Depends on what "works" means. Have you verified that the controller isn't working by checking all possible Unity joystick ids? Unity does not always assign joystick ids sequentially starting at 1. What does Input.GetJoystickNames() return? Another way to test would be to test GetKey with one of the "all joysticks" keycodes.

    If none of the above works, then there isn't any reason why it should fail. It would by default use the gamepad API, which wouldn't require special permissions. If, however, for some weird reason it isn't working through the gamepad API on your system and requires the HID API, then you'd have to add this to your manifest file:

    Code (csharp):
    1. <Capabilities>
    2.   <DeviceCapability Name="humaninterfacedevice">
    3.   <Device Id="any">
    4.   <Function Type="usage:0001 0004" />
    5.   <Function Type="usage:0001 0005" />
    6.   </Device>
    7.   </DeviceCapability>
    8. </Capabilities>
    There's also a Unity Player options setting to enable HID joysticks.
     
  4. slander36

    slander36

    Joined:
    May 26, 2016
    Posts:
    5
    tl:dr for anyone needing help. Make sure the "Force Module Active" is checked on the scene's EventSystem.

    Starting trials and errors:

    Plugging in the Xbone controller while in the Unity editor shows `Joystick connected ("Controller (Xbox One For Windows)").` which is expected.

    In Project Settings -> Input, Horizontal and Vertical are both using "Joystick Axis" "X/Y Axis" (depending), and "Get Motion from all Joysticks".

    Input.GetJoystickNames() returns "Controller (Xbox One For Windows)" in Unity Preview Preview.

    Input.GetJoystickNames() returns "Controller (Xbox One For Windows)" in Standalone. I checked the Input window for Standalone, and noticed that it defaults to "joystick 0 axis 0" for horizontal, and "joystick 0 axis 1", and after changing the input (it detected "Joystick 1 axis 0" and "Joystick 1 axis 1" for horizontal and vertical, respectively) it works.

    Input.GetJoystickNames() returns "Xbox 360 Controller for Windows" in UWP Windows 10, which is wrong. Just noticed, also, that even though the screen is auto-focused after launching from VS2015, I still have to click the window, or at very least alt-tab to it again, to get it to use the Xbone controller. This is better than it was before.

    Input.GetJoystickNames() returns "Xbox 360 Controller for Windows" in UWP Xboe One, as well. After adding a spot for GetKey("Y") with some on-screen text, it is detecting key presses, so the controller is working.

    Digging down deeper, I noticed I had added a second "Standalone Input Module" to specify A, B, JoystickX, JoystickY for the appropriate fields, and that Vertical's default is Inverted and JoystickY's was not, so even if it was working, they would be cancelling each other out. I removed the second Standalone Input Module and stopped referencing JoystickX/Y. I can now see values for Horizontal and Vertical, but the UI still isn't responding.

    So current situation: controller is working, I just hadn't tested it enough. However, it's reading as an Xbox 360 controller on the Xbox One (odd) and the UI is not responding in any way, shape, or form to input.

    Final solution: DON'T add a second "Standalone Input Module" to the EventSystem (though verdict is out on if this caused any issues and I don't feel like messing around with this right now to check), but make sure the "Force Module Active" is checked on the one that comes default. This looks like it was the main culprit, and why it felt like the controller wasn't connected. There must be some weird bug where the EventSystem starts before the game has detected a controller, and so that script just never gets initialized correctly or something /shrug.

    ----

    Sorry for the train of thought work-through, here. Hopefully people wanting to get a controller set up and working with Xbox One UWP Dev will see this first instead of making the same jumps in logic that I did.

    Thank you, guavaman, for jogging my quick-and-dirty-debug memory to print things on the screen. I was contemplating just grabbing Rewired to get around this, but can't rationalize spending the money until I've made a few more sample games.
     
    JMDigital likes this.
  5. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,645
    I can clarify why it happens. The traditional XInput API has no way to retrieve the actually xbox controller name, we just know that it's an xbox controller. So at the time we hardcoded to return "Xbox 360 Controller for Windows" in case it detects any xbox controller connected. I fixed this in 5.4 I believe to return just "Xbox Controller for Windows".
     
  6. slander36

    slander36

    Joined:
    May 26, 2016
    Posts:
    5
    Awesome. Thank you for the clarification. Makes sense.
     
  7. Flarup

    Flarup

    Joined:
    Jan 7, 2010
    Posts:
    164
    For what's it's worth: The Xbox One controller worked fine for me when running a UWP build on my Xbox One in dev mode. I didn't do anything special to get it running. I'm using Unity 5.3.4f1 and the latest developer preview of Visual Studio.
     
  8. slander36

    slander36

    Joined:
    May 26, 2016
    Posts:
    5
    No issues using UI elements? I am fine loading straight into a game, but I had put a Main Menu in front of the app I was trying to use. All input turned out to be working fine EXCEPT input which goes through the Event Manager. Beyond that, I had to force select UI elements through scripts to use them (example: Pause menu) as the "firstSelected" element didn't always seem to kick in correctly.

    Most of my issues I chalk up to working too late and looking up out-of-date guides before just seeing if it worked out of the box.
     
  9. Flarup

    Flarup

    Joined:
    Jan 7, 2010
    Posts:
    164
    My UI currently doesn't work, because it still requires you to have a mouse connected. I need to redo my UI a bit before it works with the Xbox One controller. But if I go directly to the gameplay scene then the Xbox One controller works as expected.
     
  10. slander36

    slander36

    Joined:
    May 26, 2016
    Posts:
    5
    In case you get stuck on the same issues I did, make sure that "Force Module Active" is checked for your "Standalone Input Module" in your EventSystem (I called it Event Manager earlier, got that wrong).

    Here's the code I use in two flavors, one pulling in the EventSystem, and one just using Button's own built-in .Select() function.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.UI;
    4. using UnityEngine.EventSystems;
    5. using UnityEngine.SceneManagement;
    6. using System.Collections;
    7.  
    8. public class MainMenu : MonoBehaviour {
    9.  
    10.     public string playGameLevel;
    11.  
    12.     public EventSystem es;
    13.     public GameObject firstSelected;
    14.  
    15.     public void PlayGame() {
    16.         SceneManager.LoadScene (playGameLevel);
    17.     }
    18.  
    19.     public void QuitGame() {
    20.         Application.Quit ();
    21.     }
    22.  
    23.     void Start() {
    24.         es.SetSelectedGameObject (firstSelected);
    25.     }
    26.  
    27.     void Update() {
    28.        
    29.     }
    30. }
    Code (CSharp):
    1.  
    2. public class PauseMenu : MonoBehaviour {
    3.  
    4.     public GameObject pauseMenu;
    5.  
    6.     public string mainMenuLevel;
    7.  
    8.     public Button firstSelected;
    9.  
    10.     private bool paused;
    11.  
    12.     void Start() {
    13.         paused = false;
    14.     }
    15.  
    16.     void Update() {
    17.         if (Input.GetButtonDown ("Start")) {
    18.             if (paused)
    19.                 ResumeGame ();
    20.             else
    21.                 PauseGame ();
    22.         }
    23.     }
    24.  
    25.     public void PauseGame() {
    26.         Time.timeScale = 0f;
    27.         pauseMenu.SetActive (true);
    28.         firstSelected.Select ();
    29.     }
    30.  
    31.     public void ResumeGame() {
    32.         Time.timeScale = 1f;
    33.         pauseMenu.SetActive (false);
    34.     }
    35.  
    36.     public void RestartGame() {
    37.         Time.timeScale = 1f;
    38.         pauseMenu.SetActive (false);
    39.         FindObjectOfType<GameManager> ().RestartGame ();
    40.     }
    41.  
    42.     public void QuitToMainMenu() {
    43.         Time.timeScale = 1f;
    44.         pauseMenu.SetActive (false);
    45.         SceneManager.LoadScene (mainMenuLevel);
    46.     }
    47. }
    48.  
    Even if you didn't need these, hopefully they help someone some day :)
     
  11. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,608
    The reason you have to do this is that Unity's StandaloneInputModule uses rather odd criteria to determine whether the StandaloneInputModule should be used on the current platform. Here's the part of the source code that causes it:

    Code (csharp):
    1. public override bool IsModuleSupported()
    2. {
    3.   return m_ForceModuleActive || Input.mousePresent || Input.touchSupported;
    4. }
    Edit: Updated code for 5.3 branch changes.

    One of Input.mousePresent or Input.touchSupported must be true to cause the StandaloneInputModule to be used. This will be false on Xbox One, PS4, WiiU, and many other platforms. This would be fine if the StandaloneInputModule only handled mouse and touch input, but it doesn't -- it handles keyboard and joystick input also.
     
    Last edited: Jun 1, 2016
    slander36 likes this.
  12. JMDigital

    JMDigital

    Joined:
    Mar 28, 2022
    Posts:
    2
    I love you for this, thank you so much! :)

    To add; This has to be done for every EventSystem in each scene.

    Edit: Ok so this only works with the 'old' Input system and there is no such option in the 'new' input system for Unity.

    Not sure what else to do, can't find where to 'force' the same thing anymore.
     
    Last edited: Apr 15, 2022