- Home /
Input.GetKey() with multiple enum values (C#)
Declaring
private KeyCode ForwardKey = KeyCode.W|KeyCode.UpArrow;
and calling if (Input.GetKey( ForwardKey )) { print("forwardPressed") } during Update isn't working out
Now I want to make a function that splits up the enum into separate values again so I can call getKey for every keycode given.
Answer by Bunny83 · Jan 17, 2013 at 11:45 PM
Like i said in the comment the KeyCode enum is not a bit mask and therefore the members can't be combined bitwise.
You did this:
KeyCode.UpArrow == 273 == 100010001
KeyCode.W == 119 == 1110111
-----------------------------------
ForwardKey == 101110111 == 375 == KeyCode.Joystick2Button5
You have to test your keys seperately. If you want to assign multiple KeyCodes to a certain action, use an array:
private KeyCode[] ForwardKeys = new KeyCode[] {KeyCode.W, KeyCode.UpArrow};
public static bool AnyKey(KeyCode[] aKeys)
{
foreach(KeyCode K in aKeys)
if (Input.GetKey(K))
return true;
return false;
}
// Somewhere else
if (AnyKey(ForwardKeys))
{
//
}
Now you can assign as many KeyCodes as you want.
Answer by TrevoriuS · Jan 17, 2013 at 11:48 PM
Sorry for the lack of comments, but here's what I came up with.
The StackedKeyCodesAsInt generates a valid int that is unique for every keycode combination imaginable, the modifier of 429 is the highest number in the KeyCode enum.
The IntAsExpandedKeyCodes is the backwards conversion, the other functions are wrappers to replace the Input functions. And there's that.
public static class KeyCodeManager
{
public static bool GetKeys( int keycodestack )
{
foreach (KeyCode key in IntAsExpandedKeyCodes( keycodestack ))
if (Input.GetKey( key ))
return true;
return false;
}
public static bool GetKeysDown( int keycodestack )
{
foreach (KeyCode key in IntAsExpandedKeyCodes( keycodestack ))
if (Input.GetKeyDown( key ))
return true;
return false;
}
public static bool GetKeysUp( int keycodestack )
{
foreach (KeyCode key in IntAsExpandedKeyCodes( keycodestack ))
if (Input.GetKeyUp( key ))
return true;
return false;
}
public static int StackedKeyCodesAsInt( KeyCode[] keycodes )
{
int output = 0;
int modifier = 1;
foreach (KeyCode keycode in keycodes)
{
output += modifier * (int)keycode;
modifier *= 429;
}
return output;
}
public static KeyCode[] IntAsExpandedKeyCodes( int keycodestack )
{
List<KeyCode> output = new List<KeyCode>() { (KeyCode)(keycodestack % 429) };
while (keycodestack > 429)
{
keycodestack /= 429;
output.Add( (KeyCode)(keycodestack % 429) );
}
return output.ToArray();
}
}
Do you need to have it as a single value? You know that you can only use 3 values. 4 values doesn'T fit into an int.
I would also recommend to "multiply" by a power-of-two number, that way you can use bit shift operators which are much faster than multiply and especially divide / modulo.
public static int Stacked$$anonymous$$eyCodesAsInt( $$anonymous$$eyCode[] keycodes )
{
int output = 0;
foreach ($$anonymous$$eyCode keycode in keycodes)
{
output <<= 9; // shift left by 9 bits == 512
output |= (int)keycode & 0x1FF;
}
return output;
}
public static $$anonymous$$eyCode[] IntAsExpanded$$anonymous$$eyCodes( int keycodestack )
{
List<$$anonymous$$eyCode> output = new List<$$anonymous$$eyCode>();
while (keycodestack > 0)
{
output.Add(keycodestack & 0x1FF);
keycodestack >>= 9;
}
return output.ToArray();
}
Btw if you create the single integer because you want to store it in the user configuration, convert between "array and int" only when you save / load the settings and work directly with arrays in your game. If you use it like you have it at the moment you will do the conversion every frame and produce unnecessary garbage.
Thanks for the info :) I'll go with arrays then as it is far easier to maintain, I was focussed on getting this to work the way a bitmask would work and lost track of what was actually useful
Answer by doublethink · Jan 17, 2013 at 10:56 PM
With Unity's built in Input Manager you can assign a key and an alternate key for each action known as 'axes' which can be called using a string name. You can also add your own custom actions to the input manager.
Input.GetButton("Fire1")
See http://docs.unity3d.com/Documentation/Manual/Input.html
and http://docs.unity3d.com/Documentation/ScriptReference/Input.GetButton.html
I intend to have user settings control what buttons are assigned to which action, making the Input$$anonymous$$anager not an option in this event.
I did find out bitmasking the $$anonymous$$eyCode enum doesn't work because it skips numbers in its value assignments, so passing in values with the | operator results in a different key ins$$anonymous$$d of multiple, later on seperable, values.
The reason why this doesn't work is simply the fact that $$anonymous$$eyCode IS NOT a bit mask. An integer bitmask (32 bits) would only allow 32 different keys. As you know we have a little bit more than that ;) (actually 241)
In general an enum doesn't need to be a bitmask. A bitmask is just a very special case. "normal" **enum**erations are just enumerations starting at the value 0 and increasing by 1 for each element.
Answer by Bluetoungue · Jan 17, 2013 at 11:48 PM
Here i think thisll help I used it myself but here is the C# version of course
if (Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.UpArrow))
im not sure about the uparrow just mess around with it as all
Your answer
Follow this Question
Related Questions
Gamepad input enum eType not working 0 Answers
Input.GetKey behaving strangely 2 Answers
Change view if key is pressed 4 Answers
if-else for Input.GetKey 1 Answer
How can I check if a key/button is not (!) being held down? 1 Answer