Find out which key was pressed.

Hello, I am trying to find out which key the player pressed.
So something like Input.inputString, except for all keys, not just for letters and numbers. So for example if the player presses F1 i want the key number, or some unique hash or something.

And i’m NOT trying to find out if he pressed some specific key like R or something, i want to get the number (or something) of any key he pressed.

Thanks

This is actually harder than you’d think it’d be. You can do it with the immediate mode GUI by using this: Unity - Scripting API: Event.keyCode

2 Likes

Damn, that is pretty unfortunate. I tried it and the OnGui gets executed twice for every update and not only that, in half of them the keycode is returned as None even though i am holding the key down. Luckily i can work easily around that, but still it is pretty hacky and i can’t believe they don’t give us Input.keyCode

1 Like

Not efficient code, but, this will get you the current KeyCode pressed

foreach(KeyCode kcode in Enum.GetValues(typeof(KeyCode)))
{
    if (Input.GetKey(kcode))
        Debug.Log("KeyCode down: " + kcode);
}

EDIT: by “not efficient”, I mean this should not be run within the game loop to detect input. There are 321 KeyCodes to loop through. If you were maybe doing user control remapping in an options menu, this could be useable. If we knew your use case, there may be a more elegant solution to what you are trying to do

15 Likes

Yeah I’d definitely not go that route.

You’ll probably have to combine it with checks to make sure the current event is actually a keyboard event

void OnGUI()
{
    if (Event.current.isKey && Event.current.type == EventType.KeyDown)
    {
        Debug.Log(Event.current.keyCode);
    }
}
4 Likes

Actually, if you do some testing, looping through all the keycodes is far more efficient than the OnGUI route. Just having an OnGUI call in your scripts will cause memory allocations every frame which will eventually need to be collected by the garbage collector causing periodic slowdowns. Checking 321 keycodes takes next to no time in comparison.

But do not get your keycode list every update. That will generate allocations as well. Call Enum.GetValues(typeof(KeyCode)) once on start and store those values for the duratiton.

8 Likes

Except there are keycodes that can map to the same key so you have the potential for multiple “true” scenarios. And you could pick up mouse/joystick events.

I doubt this very much. How did you prove this and what’s your definition of “far more efficient”? :slight_smile:

Simply filter them out with your own keycode list that excludes these.

From another post of mine from last year:

Just for fun I profiled it:

// Keyboard polling: 9.504352E-06 s / frame
// (as timed, avg of 1000 frames, profiler reports 0.00 ms)

private int[] values;
private bool[] keys;

void Awake() {
    values = (int[])System.Enum.GetValues(typeof(KeyCode));
    keys = new bool[values.Length];
}

void Update() {
    for(int i = 0; i < values.Length; i++) {
        keys[i] = Input.GetKey((KeyCode)values[i]);
    }
}
// OnGUI: 0.02 ms (as reported by profiler), 336 bytes GC / frame
void OnGUI() {
    // there is no code in here
}

Keyboard polling is more efficient.

16 Likes

Interesting - and certainly a concern if you’re not targeting desktop platforms.

if you want to know what character key is pressed
you can go for a textinput
an invisible textinput that detects wich key you pressed
you simply add a on value changed mathod
then you read whats in textfield and empty it again
but you should make sure that you keep the input text selected and focused

Please don’t necropost a 3-year-old thread just to post a solution that’s significantly inferior to @guavaman 's solution that was posted up above.

7 Likes

Literally the worst possible solution to that problem…

6 Likes

Far from ideal, but a very clever dirty hack indeed ^^

1 Like

See my comment above about not posting an inferior solution to an old thread. Your solution was already posted in this thread verbatim and then proven to be inferior.

See @guavaman 's comment above for information about why your solution is inferior.

I mean, basically, just read the thread before you reply to it.

3 Likes

Has just loggind to say that you are my hero, thanks, glad to you i have found name of button which i have searching for a day! Thanks

1 Like

I would add an Input.anyKeyDown check around the for loop, so the for loop would only be called when there actually is a key pressed down and not with every Update call, like so:

private int[] values;
private bool[] keys;

void Awake() {
    values = (int[])System.Enum.GetValues(typeof(KeyCode));
    keys = new bool[values.Length];
}

void Update() {
    if (Input.anyKeyDown)
    {
        for(int i = 0; i < values.Length; i++) {
            keys[i] = Input.GetKey((KeyCode)values[i]);
        }
    }
}
1 Like

My current solution after reading all the comments would be:

private readonly Array keyCodes = Enum.GetValues(typeof(KeyCode));

void Update()
{
    if (Input.anyKeyDown)
    {
        foreach (KeyCode keyCode in keyCodes)
        {
            if (Input.GetKey(keyCode)) {
                Debug.Log("KeyCode down: " + keyCode);
                break;
            }
        }
    }
}
8 Likes

Dirty, yes. Ideal, no. Clever, also no. There’s an input system for a reason…

Have you benchmarked that this has any considerable gain on performance?

to be fair that input system should allow a function like Input.getKeyUp, I have to say that danesh is at least showing more insight with that neat hack that the unity team forcing the user to go through a 3-year quest to get to a solution that doesn’t use OnGUI, you know, like getKeyDown

1 Like

I was wrong, it’s still not working properly, maybe in 3 more years