Search Unity

Simple and efficient way to detect the InputDevice currently being used

Discussion in 'Input System' started by fabiopicchi, May 30, 2019.

  1. fabiopicchi

    fabiopicchi

    Joined:
    Jan 22, 2016
    Posts:
    22
    I couldn't find in the current API (0.2.10-preview) a simple and efficient way of detecting the input device that the player is currently using. I want to do that so I can update my UI accordingly displaying, for instance, "Press start" instead of "Press enter" when using a gamepad instead of a keyboard.

    I could query all the devices every frame for any interaction made with them but I consider that solution not very scalable or efficient. Maybe we could have something as a InputDevice.current (as we have a Keyboard.current and Gamepad.current) and that would point to the last used input device.
     
    valentin56610 likes this.
  2. frarf

    frarf

    Joined:
    Nov 23, 2017
    Posts:
    27
    I don't believe there's any such API but go take a look at InputUser (https://github.com/Unity-Technologi...system/InputSystem/Plugins/Users/InputUser.cs) It is what it sounds like, you can associate multiple devices to a single user and get the current device (with some jank). I haven't used it much (unless you consider PlayerInput as counting), but it's worth a look.

    Also,
    InputSystem.onEvent
    . I'm not 100 percent on how it works but you can get whenever a device is used. I don't know if it processes noisy controls though.
     
    Last edited: Jun 2, 2019
    fabiopicchi likes this.
  3. Justinas_Ma

    Justinas_Ma

    Joined:
    May 8, 2014
    Posts:
    31
    Yup, I'd second a similar feature. I use it not only in the intro screen, but in our game you can just start using another input and it simply adapts runtime, by changing prompts and control scheme. I'd love to keep this feature. So getting a device(s) binding that last affected the action would be nice. Seems not ambiguous at least for non-continous actions.
     
  4. jonas-echterhoff

    jonas-echterhoff

    Unity Technologies

    Joined:
    Aug 18, 2005
    Posts:
    1,666
    It is not trivial what "detecting the input device that the player is currently using" means.

    -There can be more then one player
    -There can be more then one device being used by a player (for instance Keyboard WASD + Mouse)

    If you use the PlayerInput class, you can get the devices currently used for each player using `PlayerInput.devices`. For general actions, you can use `CallbackContext.control.device` to find which device is driving the action (and you could use that to remember the last one).
     
    Donderbos likes this.
  5. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    978
    @jonas-echterhoff

    I'm attempting to do this in a bit of a simpler way than using the callbackcontexts.

    However, I tried go through all the devices and my devices are always null. Is this a bug?
    The error "no devices found!" from the code below is called constantly.

    When I use the CallbackContext I am capable of getting the device that calls the function.

    I think it would be nice if the controlSchemes had a isLastSchemeUsed boolean. In my opinion it doesn't matter that there could be more than one player, the fact that it was the last device used still holds true. A similar for devices would be cool too.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public class Inputer : Singleton<Inputer>
    5. {
    6.     public static Controls Control;
    7.     public static InputDevice LastUsedDevice { get; private set; }
    8.  
    9.     void Awake()
    10.     {
    11.         Control = new Controls();
    12.         Control.Enable();
    13.         Control.Player.Enable();
    14.         Control.UI.Enable();
    15.     }
    16.  
    17.     private void Update()
    18.     {
    19.         double smallestUpdateTime = double.MaxValue;
    20.         if (Control.devices != null)
    21.         {
    22.             foreach (var d in Control.devices)
    23.             {
    24.                 Debug.Log("running devices check: " + d.lastUpdateTime + " device name: " + d.name);
    25.                 if (d.lastUpdateTime < smallestUpdateTime)
    26.                 {
    27.                     smallestUpdateTime = d.lastUpdateTime;
    28.                     LastUsedDevice = d;
    29.                 }
    30.             }
    31.         }
    32.         else
    33.         {
    34.             Debug.LogError("no devices found!");
    35.         }
    36.     }
    37. }
    I think I've set up my control schemes and devices correctly because in this window they seem to be properly set up

    upload_2019-7-7_16-24-58.png
     
    Last edited: Jul 7, 2019
  6. joaorequiao

    joaorequiao

    Joined:
    Oct 15, 2015
    Posts:
    6
    Any luck here?
     
    valentin56610 likes this.
  7. valentin56610

    valentin56610

    Joined:
    Jan 22, 2019
    Posts:
    156
    Man I desperately need this… no update on this, uh…?
     
  8. JohnnyConnor

    JohnnyConnor

    Joined:
    Aug 10, 2020
    Posts:
    42
    I'm using InputDevice.displayName to check this (from InputSystem.onActionChange), but it sucks to rely on strings for comparisons, and the documentation doesn't tell what strings this property can return.

    Edit:
    Here are some return strings I've found so far:
    Mouse -> "Mouse"
    Keyboard -> "Keyboard"
    Xbox-like controllers -> "Xbox Controller"

    I don't have other gamepads to test to find more strings, but based on what I got on my Xbox-like controller, I believe the other controllers should display these names found in the binding section of an Input Action Asset:

    Capture.PNG
     
    Last edited: Jan 26, 2024
    valentin56610 likes this.