Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Two identical joysticks?

Discussion in 'Input System' started by Innovine, Mar 5, 2019.

  1. Innovine

    Innovine

    Joined:
    Aug 6, 2017
    Posts:
    529
    How can I create bindings in the Action Maps to a button or axis on ONE of two identical joysticks?

    I have two Thrustmaster 16000M joysticks attached to my PC, and the unity input debugger shows these as two different devices (one has a '1' appended to its name), yet when I try to bind, I only get Specific Devices->Joysticks->Thrustmaster 16000M. A binding to that is triggered by both sticks. If I use the learn function, unity does not see a difference between the sticks. However, in the InputAction.CallbackContext I can see that the device name is different, depending on which one I use. I would really like to solve this in the action mapping and not in the actual handler...
     
  2. Innovine

    Innovine

    Joined:
    Aug 6, 2017
    Posts:
    529
    Guys I could really do with some tips on what to do here. Is this a use case which you've simply not considered yet? Is there some way to handle this that I haven't discovered?
     
  3. Heimlink

    Heimlink

    Joined:
    Feb 17, 2015
    Posts:
    29
    I thought there were docs somewhere, at some point. But I can't seem to find them.

    First, you need to create an instance of your InputActionAssetReference. Then you need to call ApplyBindingOverridesOnMatchingControls(InputDevice) on the InputActionMap you want to use.

    Please excuse my crude example; I have a PlayerManager MonoBehaviour with the following code:

    Code (CSharp):
    1. // Reference to your Input Action asset.
    2. [SerializeField]
    3. InputControls inputControls;
    4. ...
    5.  
    6. void Awake()
    7. {
    8.     ...
    9.     // Loop through your players
    10.     for (var i = 0; i < players.Length; ++i)
    11.     {
    12.         var player = player[i];
    13.        
    14.         // Create a clone of your input asset
    15.         var controls = new InputControls(Instantiate(inputControls.asset));
    16.         // Bind your actions to your input device.
    17.         controls.ActionMap.Get().ApplyBindingOverridesOnMatchingControls(player.InputDevice);
    18.         // Set your callbacks to your handler (I use this class)
    19.         controls.ActionMap.SetCallbacks(this);
    20.     }
    21.     ...
    22. }
    Hope that points you in the right direction.

    There are some helper methods, if you have a game object per player. For example...
    Code (CSharp):
    1. // Helper method to clone the Input Action asset.
    2. gameControls.MakePrivateCopyOfActions();
    3. gameControls.ActionMap.Get().ApplyBindingOverridesOnMatchingControls(player.InputDevice);
    4. gameControls.ActionMap.SetCallbacks(this);
    I also believe they're implementing some User/Player management classes, as per UserManagement Docs, However, they don't appear to be ready in the latest release (0.2.0-preview).

    Good luck!
     
  4. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Sorry to leave you hanging there @Innovine.

    The kind of setup that @Heimlink describes is one way to go about it, though there's been a few additions since to make it easier. Overall, the idea is that every player gets a copy of the actions and then each player is restricted to specific devices. ApplyBindingOverridesOnMatchingControls() used to be the only way to do that but these days you can simply assign devices to the whole asset or to individual maps through the "devices" property and that does the trick.

    However, there's also a new set of components that are meant to make all this setup largely automatic. One is the PlayerInput component, the other is the PlayerInputManager component. Unfortunately, we don't yet have much documentation on those and there's still some unfinished work in there. The only thing as far as help goes is a crappy video I recorded a while ago.

    Basically, the idea is that each PlayerInput represents one player and, by default, no two players will end up with the same device. So if you have two Logitech joysticks, each player would get only one specific one and only receive input from that one.
     
  5. Innovine

    Innovine

    Joined:
    Aug 6, 2017
    Posts:
    529
    Thanks @Rene-Damm
    I suppose there's nothing stopping me having two PlayerInputs, one for each hand? (Its a single player, dual-stick game).
    I got this working by wrapping the InputSystem with my own thing which is able to look at the CallbackContext, and that works for now, although I cant take advantage of any of the fancy Action Mapping stuff. I think for now I will just leave this in place until the PlayerInput components are a bit more mature, and then revisit the whole input thing again. Will anything happen there in the next few months?
     
  6. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Yup, that's fine, too.

    Alternatively, you can set things explicitly for handedness. There's support for "usages" on devices. E.g. a device can be marked as having "LeftHand" usage and you can bind specifically to devices with that usage.

    In the UI, this is supported out of the box for XR controllers, but unfortunately, for other controllers it currently requires dropping the control paths into text mode and manually editing them.

    If you want to give this a try, simply pick a control, say the trigger on a joystick, drop it into text mode (in the current UI that's the "..." button; in the next package, it's the "T" button which is a toggle now), and edit the path like

    Code (CSharp):
    1. // From something like
    2. <Joystick>/trigger
    3.  
    4. // To something like
    5. <Joystick>{LeftHand}/trigger
    At runtime, you can simply assign usages to the devices you have. Like, for example:

    Code (CSharp):
    1. InputSystem.SetDeviceUsage(firstJoystick, CommonUsages.LeftHand);
    2. InputSystem.SetDeviceUsage(secondJoystick, CommonUsages.RightHand);
    This works for arbitrary usages. You can also come up with your own instead of using "LeftHand" and "RightHand". In the end, it's just string tags. You can also have more than one on a device.

    In this setup, you can also forego PlayerInput and don't need to worry about duplicating actions or any other multiplayer concerns. The usages disambiguate input from the devices sufficiently.

    For actions, it's mainly bugfixing and polishing that will happen. Overall, we're more or less feature complete. Couple of lose ends to tie up around PlayerInput. Otherwise, there's a few things to do around UI support, work around improving rebinding support, and polishing/improving the editor UI. And yeah, fixing and fixing and fixing :)
     
  7. web76

    web76

    Joined:
    Nov 4, 2009
    Posts:
    150
    Hi; I also have two Thrustmaster T.16000m Joysticks, and want to seperate the input from the two joysticks into lefthand and righthand.. I cannot get it to work, I guess I am missing some steps..
    I have 2021.3.11f and use both input packages, the new package is 1.5.0..
    This is a rather old post so maybe something changed.

    Can anyone help me with all the steps needed?
     
  8. web76

    web76

    Joined:
    Nov 4, 2009
    Posts:
    150
    This is the script, I get the two joysticks to show as Righthand and Lefthand but somehow the value is not passed..

    Any thoughts?


    Code (CSharp):
    1. using UnityEngine.InputSystem;
    2. using UnityEngine;
    3. using System.Collections.Generic;
    4.  
    5. #if UNITY_EDITOR
    6. using UnityEditor;
    7. #endif
    8.  
    9. #if UNITY_EDITOR
    10. [InitializeOnLoad]
    11. #endif
    12. public static class InitCustomDeviceUsages
    13. {
    14.     static InitCustomDeviceUsages()
    15.     {
    16.         Initialize();
    17.     }
    18.  
    19.     [RuntimeInitializeOnLoadMethod]
    20.     private static void Initialize()
    21.     {
    22.         InputSystem.RegisterLayoutOverride(@"
    23.           {
    24.               ""name"" : ""JoystickConfigurationUsageTags"",
    25.               ""extend"" : ""Joystick"",
    26.               ""commonUsages"" : [
    27.                   ""LeftHand"", ""RightHand""
    28.               ]
    29.           }
    30.       ");
    31.     }
    32. }
    33.  
    34.  
    35. public class CustomDeviceUsages : MonoBehaviour
    36. {
    37.    
    38.  
    39.  
    40.     protected void OnEnable()
    41.     {
    42.         List<InputDevice> joysticks = new List<InputDevice>();
    43.  
    44.         foreach (InputDevice device in InputSystem.devices)
    45.         {
    46.             if (device.description.product == "T.16000M") joysticks.Add(device);
    47.         }
    48.  
    49.         InputSystem.SetDeviceUsage(joysticks[0], CommonUsages.LeftHand);
    50.         InputSystem.SetDeviceUsage(joysticks[1], CommonUsages.RightHand);
    51.     }
    52.  
    53.  
    54. }
    upload_2023-3-8_14-39-12.png
    upload_2023-3-8_14-40-39.png
     
  9. AvadhutTawar

    AvadhutTawar

    Joined:
    Jul 16, 2022
    Posts:
    1
    I also having similar problems with two Logitech extreme 3d pro Joystick Direction in unity new input system, did you found any solution?

    upload_2024-1-23_16-53-14.png
     
  10. web76

    web76

    Joined:
    Nov 4, 2009
    Posts:
    150
    I had to use the old input system only for those two joysticks, in the old input system the signals on the identical joysticks are separated