Search Unity

Question Key down event in unity

Discussion in 'Scripting' started by cestop42, Mar 18, 2023.

  1. cestop42

    cestop42

    Joined:
    May 9, 2022
    Posts:
    10
    How to get data what I press the key in unity?

    like a getch method in cpp
     
    Last edited: Mar 18, 2023
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,692
    Input.inputString
    is about the closest you can get to good old
    getc(3)


    Not sure what the answer would be in the new InputSystem, so in that case check over those docs.
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    There is also Event.keyCode:
    https://docs.unity3d.com/ScriptReference/Event-keyCode.html

    But this is through the legacy OnGUI Event system. This does not really rely on the Update loop (it can happen multiple times per frame). But this is how TextMeshPro does its input stuff.

    If you need it for doing UI input, like TextMeshPro's InputField, that's how you may want to do it (you can view the source of TextMeshPro to see how it works... it's not exactly a single function call though).

    If you're attempting to do gameplay through this though, it's not really how Unity's input system works.

    ...

    Question, what is it you're attempting to accomplish?
     
    Ryiah, Bunny83 and Kurt-Dekker like this.
  4. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,992
    Yes, but even uGUI still uses this system partially. Since uGUI came out they have added the static method Event.PopEvent which is used internally by components like the UI.Input field. Though as the name of that method suggests, it actually pops the event from the event queue. So only a single consumer can process events through this method. So you have to be careful how to handle it. Using the OnGUI callback is usually the simplest solution.

    That's one of the annoying things with Unity. They added the PopEvent method but didn't add a PushEvent. Having a PushEvent method would open up so many possibilities, especially when it comes to custom event mapping or testing scenarios.

    The fact that OnGUI is called for multiple events shouldn't really matter. Yes, it's usually called twice each frame to handle the layout and repaint event, though the layout event can be disabled (with all the consequences). Since you usually filter the events by the event type, it's quite easy to ignore events you're not interested in.

    Apart from Unity specific solutions, you can always use platform specific solutions. So when you're building a windows standalone application, you could use a message hook to intercept window messages or use things like GetKeyState or GetKeyboardState. Though it depends on your exact usecase. Of course the OnGUI solution is much better for staying cross-platform.
     
  5. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    Note I didn't call it legacy as a suggestion you shouldn't use it.

    I called it legacy, because it's a legacy system. And that clarification was to follow on that it does not rely on the Update loop directly. That's the intent of the "but".
     
  6. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,147
    Here's how you would access the key code in the new input system:
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public class KeyTest : MonoBehaviour
    5. {
    6.     private void Update()
    7.     {
    8.         foreach (var key in Keyboard.current.allKeys)
    9.         {
    10.             if (key.wasPressedThisFrame)
    11.             {
    12.                 Debug.Log($"Key code: {key.keyCode}");
    13.             }
    14.         }
    15.     }
    16. }
    Getch() works by pausing input until a character has been received. We can't do that in Unity so we instead have to track if one has been received:
    Code (csharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public class KeyTest : MonoBehaviour
    5. {
    6.     private KeyCode lastKeyPressed;
    7.     private bool keyPressed;
    8.  
    9.     public KeyCode LastKeyPressed
    10.     {
    11.         get
    12.         {
    13.             KeyCode tmp = lastKeyPressed;
    14.             lastKeyPressed = KeyCode.None;
    15.             keyPressed = false;
    16.             return tmp;
    17.         }
    18.     }
    19.  
    20.     public bool KeyPressed
    21.     {
    22.         get
    23.         {
    24.             return keyPressed;
    25.         }
    26.     }
    27.  
    28.     private void Update()
    29.     {
    30.         if (!keyPressed)
    31.         {
    32.             foreach (var key in Keyboard.current.allKeys)
    33.             {
    34.                 if (key.wasPressedThisFrame)
    35.                 {
    36.                     lastKeyPressed = key.keyCode;
    37.                     keyPressed = true;
    38.                     break;
    39.                 }
    40.             }
    41.         }
    42.     }
    43. }
    The second script was written with the help of GPT-4. I haven't tested it but it should work.
     
    lordofduct likes this.