Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Check if any key is pressed

Discussion in 'Input System' started by Synpse, Oct 19, 2019.

  1. Synpse

    Synpse

    Joined:
    Mar 19, 2018
    Posts:
    20
    As the title suggests, how can I check if any key was pressed on this new system? Also how can I know what key it was?

    Thank you
     
    Eristen likes this.
  2. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    You can use:
    Code (CSharp):
    1. Keyboard.current.anyKey.wasPressedThisFrame
    It detects if any key was pressed, but I think it doesn't expose the specific key name? I'm just learning this new Input System myself.
     
    Eristen and Synpse like this.
  3. Synpse

    Synpse

    Joined:
    Mar 19, 2018
    Posts:
    20
    That might work. Do you think there is a way of getting input from any device? Per example:

    Code (CSharp):
    1. AnyDevice.current.anyKey.wasPressedThisFrame
    Do you think this might be possible?
     
  4. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    ATM there's no good, simple way to to that. It's on the list for after 1.0 as it's indeed a hole in the system.

    Binding-wise, it is possible to do

    Code (CSharp):
    1. var action = new InputAction(type: InputActionType.PassThrough, binding: "*/<Button>");
    2.  
    3. // In update code:
    4. if (action.triggered) //...
    but doing so is very inefficient.

    An alternative is doing it at the event level but it requires a good chunk of code.

    Code (CSharp):
    1. // Sets m_ButtonPressed as soon as a button is pressed on
    2. // any device.
    3. InputSystem.onEvent +=
    4.     (eventPtr, device) =>
    5.     {
    6.         if (!eventPtr.IsA<StateEvent>() && !eventPtr.IsA<DeltaStateEvent>())
    7.             return;
    8.         var controls = device.allControls;
    9.         var buttonPressPoint = InputSytem.settings.defaultButtonPressPoint;
    10.         for (var i = 0; i < controls.Count; ++i)
    11.         {
    12.             var control = controls[i] as ButtonControl;
    13.             if (control == null || control.synthetic || control.noisy)
    14.                 continue;
    15.             if (control.ReadValueFromEvent(eventPtr, out var value) && value >= buttonPressPoint)
    16.             {
    17.                 m_ButtonPressed = true;
    18.                 break;
    19.             }
    20.         }
    21.     };
     
    idbrii likes this.
  5. Synpse

    Synpse

    Joined:
    Mar 19, 2018
    Posts:
    20
    I don't dislike that second alternative. It's ugly but it looks like it will work.
    The thing is I don't understand what most of those things do, stuff like "IsA(), controls.synthetic, controls.noisy...". Are those documented on the new input's API?
     
  6. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    For the most part, yes. We have holes (mostly with lower-level stuff) but both InputControl.synthetic and InputControl.noisy, for example, are documented.
     
  7. Synpse

    Synpse

    Joined:
    Mar 19, 2018
    Posts:
    20
    Thanks for the links!
     
  8. cxode

    cxode

    Joined:
    Jun 7, 2017
    Posts:
    268
    I'm having an issue with Keyboard.current.anyKey.wasPressedThisFrame. If I hold down one key, then press a second key, it remains false. This is a regression from the old system's Input.anyKey.

    Is this intended behavior? If so, is there a workaround? Currently I'm iterating through every Key to individually check if it's down this frame, I feel like there must be a better way...

    CC @Rene-Damm -- hope it's okay to ping you
     
    PersianKiller likes this.
  9. NongBenz

    NongBenz

    Joined:
    Sep 30, 2014
    Posts:
    26
    I'm experiencing the same issue, "anyKey.wasPressedThisFrame" doesn't trigger when holding a second key so shift/ctrl shortcuts I've set up don't function. We're you able to find a solution/workaround?
     
  10. cxode

    cxode

    Joined:
    Jun 7, 2017
    Posts:
    268
    @NongBenz I wasn't able to find a non-S***ty way of doing it, the workaround I'm using is what I already described: I iterate through every Key and check individually whether one is down.
     
  11. GrayedFox

    GrayedFox

    Joined:
    Jan 28, 2014
    Posts:
    70
    Is there a simpler way to do this now?
     
    valentin56610 likes this.
  12. CraftedGaming

    CraftedGaming

    Joined:
    Jun 9, 2017
    Posts:
    35
    *bump
    any updates? @ unity
     
  13. tonycoculuzzi

    tonycoculuzzi

    Joined:
    Jun 2, 2011
    Posts:
    301
    Is this still tedious, or has an easier way been implemented? I have to admit, I can't believe the new input system shipped without an easy way to accomplish this.
     
  14. jaypordy

    jaypordy

    Joined:
    Feb 25, 2020
    Posts:
    2
    Any luck with this?
     
    valentin56610, FVS and pawerfulgames like this.
  15. FVS

    FVS

    Joined:
    Aug 10, 2015
    Posts:
    56
    "Any key" is supposed to be easy, but it seems it's confusing for both the programmers and the customers
    Any update on this though?
    upload_2021-7-10_14-44-23.png
     
  16. PapaGrizzle

    PapaGrizzle

    Joined:
    Mar 17, 2018
    Posts:
    2
    Has anyone had any luck finding anything out, as far as a simpler solution?
     
    valentin56610 likes this.
  17. FVS

    FVS

    Joined:
    Aug 10, 2015
    Posts:
    56
    I used #4 and it worked for me
     
  18. CraftedGaming

    CraftedGaming

    Joined:
    Jun 9, 2017
    Posts:
    35
    PapaGrizzle likes this.
  19. PapaGrizzle

    PapaGrizzle

    Joined:
    Mar 17, 2018
    Posts:
    2
    SpicyPaper likes this.
  20. CassioTDS

    CassioTDS

    Joined:
    Jan 21, 2020
    Posts:
    12
    Well, here's the code then (extracted from here):
    Code (CSharp):
    1. public KeyCode getCurrentKeyDown()
    2.     {
    3.         KeyCode finalKeyCode=KeyCode.None;
    4.         foreach (KeyCode kcode in Enum.GetValues(typeof(KeyCode))){if (Input.GetKey(kcode)){ finalKeyCode = kcode; }}
    5.         if (finalKeyCode == KeyCode.None)
    6.         {
    7.             //Couldn't find key
    8.         }
    9.         return finalKeyCode;
    10.     }
    upload_2021-8-15_15-21-17.png
     
  21. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Upcoming 1.1-pre.6 finally adds an API for this.

    Code (CSharp):
    1. InputSystem.onAnyButtonPress
    2.     .CallOnce(ctrl => Debug.Log($"{ctrl} pressed"));
     
  22. cxode

    cxode

    Joined:
    Jun 7, 2017
    Posts:
    268
    Bless up, thank you very much Rene.
     
    valentin56610 likes this.
  23. watson1423

    watson1423

    Joined:
    Oct 21, 2019
    Posts:
    2
    i se some of you guys have the same problem as me i had solved it for keyboard using the key name like this
    Code (CSharp):
    1. if (Keyboard.current.FindKeyOnCurrentKeyboardLayout(Keyboard.current.allControls[KeyIndex].displayName).wasPressedThisFrame)
    it returns true if the key index is pressed but it dowsnt work for mouse and i havent tried gamepad yet

    edit: Gamepad also doesnt support i am gona do a classic gamer move and just save last state of the buttons with the press tag so it catches diferences
     
    Last edited: Feb 25, 2022
  24. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    10,078
    https://forum.unity.com/threads/input-system-1-3-0-released-more-fixes.1222632/#post-7862056

    Make sure you read the following discussion too. Don't treat everything as "button", users aren't so no need.
     
  25. Zephni

    Zephni

    Joined:
    Apr 23, 2015
    Posts:
    100
    If anyone else couldn't use this code because .CallOnce wasn't available, make sure to use:

    Code (CSharp):
    1. using UnityEngine.InputSystem.Utilities;
     
    Last edited: Sep 16, 2022
  26. Wriggler

    Wriggler

    Joined:
    Jun 7, 2013
    Posts:
    124
    Thank you, that totally helped me. This is the second time I've been completely confused today by this crazy API using extension methods everywhere. The InputSystem is a cool thing, but the API is probably the most over engineered and over complicated set of code in the whole of Unity (!). It's sooooo hard to figure it out organically...

    Ben
     
    valentin56610, Zephni and cxode like this.
  27. cxode

    cxode

    Joined:
    Jun 7, 2017
    Posts:
    268
    I wholeheartedly agree. I literally wrote my own custom API on top of the built-in one just because I can't F***ing stand the built-in API.
     
    valentin56610 likes this.
  28. pastaluego

    pastaluego

    Joined:
    Mar 30, 2017
    Posts:
    193
    I tried

    Code (CSharp):
    1. InputSystem.onAnyButtonPress.CallOnce(ctrl => Debug.Log($"{ctrl} pressed"));
    and it detects false presses every frame with nothing touching the controller

    "Button:/adapter/hat/right pressed"
    and
    "Button:/adapter2/hat/right pressed"

    I don't know what either of those buttons even are, but the Input Action Asset doesn't detect them when using the "Listen" button for mapping the joystick adapter. The "Listen" button works in the asset, but I need the accurate runtime detection of any button press.

    Is there anything better?
     
  29. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,983
    Even in 1.5 there is nothing that checks for *any* input. I wanted an idle detector which would bail if gyro or joystick or touchpad was significantly moved, in addition to buttons, but had to write my own. And of course, it should be a mark/sweep in the bowels of the input system, not a caller polling thing done way up in the game loop.
     
  30. pastaluego

    pastaluego

    Joined:
    Mar 30, 2017
    Posts:
    193
    And by your own you mean you just checked a list of every possible input every frame to see if it's pressed?
     
  31. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,983
    See post #4 in this thread, but duplicate lines 12~19 for AxisControl, Vector2Control, ... and so on.
     
  32. pastaluego

    pastaluego

    Joined:
    Mar 30, 2017
    Posts:
    193
    Sadly that also gives false positives with my adapter for all 4 controller slots even without a controller plugged in. It receives 4 STAT events every frame for each slot when that method is added to the onEvent listener. Don't know what a STAT event is, but it doesn't seem filterable. It's the eventPtr.type which is a FourCC struct, but I don't know what a FourCC is, but its ToString() gives "STAT".
     
  33. Plybs

    Plybs

    Joined:
    Jan 22, 2021
    Posts:
    6
    This does not work if you press more than one key at once. Holding right arrow then pressing left arrow for example will output "right arrow pressed" on every press and release.
    There also doesn't seem to be a way to get key released events with this method.
     
    Last edited: Jun 3, 2023
  34. Plybs

    Plybs

    Joined:
    Jan 22, 2021
    Posts:
    6
    Throws an error
    "Operator '+=' cannot be applied to operands of type 'InputEventListener' and 'lambda expression' "
     
  35. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,150
    You will have to subscribe an object that is implementing the
    IObserver<InputEventPtr>
    interface. Using that you can get the last used device by using the API.

    It may not be the most performant solution (and you may have to filter out some noise) but it works for all inputs (keys, mouse move, buttons, thumbsticks, ...).

    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4.  
    5. #if ENABLE_INPUT_SYSTEM
    6. using UnityEngine.InputSystem;
    7. using UnityEngine.InputSystem.LowLevel;
    8. #endif
    9.  
    10. namespace YourNameSpace
    11. {
    12.     public partial class InputDetector : IObserver<InputEventPtr>
    13.    {
    14.  
    15.         public void Init()
    16.         {
    17.             InputSystem.onEvent.Subscribe(this);
    18.         }
    19.  
    20.         public void OnCompleted() {}
    21.         public void OnError(Exception error) {}
    22.  
    23.         public void OnNext(InputEventPtr value)
    24.         {
    25.             for (int i = 0; i < InputSystem.devices.Count; i++)
    26.             {
    27.                 if (InputSystem.devices[i].deviceId == value.deviceId)
    28.                 {
    29.                     var device = InputSystem.devices[i];
    30.  
    31.                     // Thanks to:
    32.                     // https://forum.unity.com/threads/detect-most-recent-input-device-type.753206/#post-9167348
    33.  
    34.                     // Some devices like to spam events like crazy.
    35.                     // Example: PS4 controller on PC keeps triggering events without meaningful change.
    36.                     var eventType = value.type;
    37.                     if (eventType == StateEvent.Type)
    38.                     {
    39.                         // Go through the changed controls in the event and look for ones actuated
    40.                         // above a magnitude of a little above zero.
    41.                         if (!value.EnumerateChangedControls(device: device, magnitudeThreshold: 0.0001f).Any())
    42.                             continue;
    43.                     }
    44.  
    45.                     if (device == Mouse.current)
    46.                     {
    47.                         Debug.Log("Mouse");
    48.                     }
    49.                     else if (device == Keyboard.current)
    50.                     {
    51.                         Debug.Log("Keyboard");
    52.                     }
    53.                     else if (device == Gamepad.current)
    54.                     {
    55.                         Debug.Log("GamePad");
    56.                     }
    57.                     else
    58.                     {
    59.                         Debug.Log("Other device");
    60.                     }
    61.                     break;
    62.                 }
    63.  
    64.             }
    65.            
    66.         }
    67.  
    68.     }
    69. }
     
    Last edited: Sep 19, 2023