- Home /
KeyCodes for non-US keyboard layouts
Hi there,
I am currently working on an interactive visualization of a typewriter. To make the typing look realistic, I need information about the state of the keys on the keyboard (key is pressed, key is released).
In Unity, as I understand, such things seem to be done with either (for example)
Input.GetKeyDown(KeyCode.LESS)
or, in OnGUI(), with
if((Event.current.type == EventType.KeyDown) &&
(Event.current.keyCode == KeyCode.LESS))
//do things
and their equivalent KeyUp methods. Because things did not do what they should, I looked for what KeyCodes are sent:
if(Event.current.type == EventType.KeyDown)
Debug.Log(Event.current.keyCode)
And I see strange things happening. I am in Germany, my keyboard layout is set to german, nothing is changed from standard settings and works well in the whole (german) Windows system. Keys like A,S,D,2
do what they should do and print A,S,D,Alpha2
.
But keys like <,,#,+ print definitely NOT the keyCodes they should - for example, <,#, all print "BACKSLASH".
If I print Event.current.character, everything is fine ("<" prints "<"), but there seem to be localization problems with the keyCodes. I have tested this with different machines with both Unity2.5 and Unity2.6, and the problem persists. Is this a bug?
Is there any way I can get proper key-Events inside Unity without using this Method? Apart from the problems listed here, I would also need a keyCode for the key, but this one isn't even there in Unity (http://panther.unity3d.com/support/documentation/ScriptReference/KeyCode.html).
If there is no other way, I will probably have to write something like a keyHooker DLL, but that would be really not the "way it should be".
Any help would be greatly appreciated.
The $$anonymous$$eyCode documentation says that key codes "map directly to a physical key" -- so I don't understand why we get different codes when keyboard language settings change? I can confirm that it happens, but to me it seems like a bug. (It's now three years after the original post, and I'm using Unity 3.5.6.)
Answer by fherbst · Jun 09, 2010 at 10:37 AM
By slightly changing Mike's Code from another post, I was able to use the system events for determining the state of non-standard buttons.
using UnityEngine; using System.Collections;
using System.Runtime.InteropServices;
public class keyStateTester : MonoBehaviour {
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
protected static extern short GetKeyState(int keyCode);
public int GetEszett()
{
ushort i = (ushort)GetKeyState(219);
return i;
}
// Update is called once per frame
void Update ()
{
if(GetEszett() != 0)
Debug.Log("Eszett has done something");
}
}
So, this is a way to go by using an external DLL. I would like a solution without using a DLL better, because I initially thought about publishing the project on the web, too...
Maybe someone has a solution without using a dll?
Unless you can get the System.Windows.Forms method of hooking into the system input events working, most likely this is your only route. I did just have an interesting idea though, I'll have a play with it to see if it's viable and let you know later
O$$anonymous$$, I mark this thread as solved. It would be great if you manage to go another way, though.
one question ... is $$anonymous$$eycode.A mean the actual physical location of A regardless of whether its A or not? say i have a dvorak keyboard would i still need to use qwerty physical markers? on a dvorak , ins$$anonymous$$d of ASDF, its AOEU.. so if i want the user to type O , it would be $$anonymous$$eyCode.S ???
if that's the case then simply use the Qwerty equivalent to where our German code is...
Answer by jonas-echterhoff · Jun 09, 2010 at 01:15 PM
The KeyCodes will not correctly map to the keys on your keyboard, as keycodes (unlike character codes) are used to label physical keys, not their mapping to characters. Now, the KeyCode enums will all reflect the key names on a US-keyboard. While that may be misleading, it makes sense, because it's better then having no names at all. So, getting wrong keycodes for your german keyboard layout is by design here. If, however, you are getting the same key code reported for multiple different keys, then something is clearly wrong. Please verify this, and report a bug with instructions to reproduce.
Not sending characters on keyUp events also has somewhat of a reason, which is that with IME input, keystrokes will no longer directly map to characters, as multiple keystrokes may be needed to input a character, or single keystrokes may input multiple characters. I'm not sure how this should be treated for simple mappings, though, and it may be inconsistent right now. I will make a note to do some testing on this.
In Delphi there is a On$$anonymous$$eyDown-Event which returns the keyCode as integer. For example, pressing the ""-$$anonymous$$ey returns 219.
Additionally, there are virtual keyCodes like in Unity, which are just constants (e.g. V$$anonymous$$_F1 = 112), not enums. Of course, not every possible physical key has a keyCode-name, but With this method, one is able to use every physical key even if there is no keyCode for it.
$$anonymous$$aybe there could be implemented an alternative Get$$anonymous$$eyDown method like this? :)
$$anonymous$$eyCodes in Unity should be exactly the same. 219 maps to V$$anonymous$$_OE$$anonymous$$_4 in the windows headers, which Unity maps to $$anonymous$$eyCode.LeftBracket (which that key is on a US keyboard).
Why Unity3D even only delivers the hardware Scan Code? Every normal application is delivering the virtual key... wasted the whole day trying to map the scan code to a localized char/virtual key, but I couldn't figure out (though I got most keys working, but hacky). There needs to be Event.current.virtual$$anonymous$$eyCode.
Now I ended up using an Interop keylogger to get the real virtual key codes...
Answer by Mike 3 · Jun 09, 2010 at 09:21 AM
Most likely it's not a bug - if they had to put every unicode character into the enum, it'd be completely unusable
Is there a reason character isn't of any use to you? If i remember correctly, there are functions in .NET to get a system keycode value from one
In other languages (Delphi, for example) keyCodes are sent as a kind of Integer, so there you could use every key on every keyboard whose Unicode character you know.
Event.current.character only gets sent on $$anonymous$$eyDown events. On $$anonymous$$eyUp events, only the keyCode (which is wrong) gets send. And because I have to distinguish between the keys, I can't simply release all keys when a $$anonymous$$eyUp Event occurs.
I have looked for .NET functions, but were not able to use them inside my Unity code; maybe I've done something wrong. Could you paste a link or a sample where I can get more information?
I was thinking of just (int)yourChar actually. but you're right - it's a bit silly if it's not sending the character on keyup too.
Your answer
Follow this Question
Related Questions
key binding 0 Answers
checking for keyboard input with exceptions 0 Answers
Event Trigger For Key Pressed 4 Answers