Ensuring only one key is being pressed at a time.

There’s a brief mini-game within my game that requires the player to press a certain key repeatedly. The key they have to press changes every few seconds (there’s four possible keys total – Z, X, N, M), and they only get points if they’re pressing the correct key.

The game works perfectly, but the problem I’m having is that you can just press all four keys repeatedly throughout the game without penalty. Pressing multiple keys at once should cause the score to stall or decrease.

I’ve tried a few different ways to accomplish this, but none seem to work. Creating a counter that tracked how many keys are being pressed seemed to make the most sense, but since the keys are being pressed so rapidly (and simultaneously), GetKeyDown and GetKeyUp didn’t seem able to keep up.

I also thought about putting all the KeyCodes in an array and then telling the game not to add to the score if any of the other keys were being pressed except the current one. But I couldn’t quite figure out how to do this, and even if I could, it would likely require looping through the array every frame, which isn’t ideal.

This seems simple, but I can’t seem to find anyone else with quite the same issue.

Anyone have an ideas? Thanks!!

Use just plain GetKey, which returns true the entire time the key is held down. Check them each frame.

void Update() {
int keyCounter = 0;
if (Input.GetKey(KeyCode.Z) ) keyCounter++;
if (Input.GetKey(KeyCode.X) ) keyCounter++;
if (Input.GetKey(KeyCode.N) ) keyCounter++;
if (Input.GetKey(KeyCode.M) ) keyCounter++;
if (keyCounter == 1) {
//your existing code
}

You could also put the applicable keycodes in an array and loop through them, but I figure this is a more straightforward modification to your existing code.

Ah, perfect! It works!

I had tried using GetKey before, but I either made the mistake of instantiating the key counter outside of Update, or unthinkingly used else-if statements instead. This way, the counter resets every frame, and it works just great! Thanks so much!

If you do this way (or similar):

boolean[] pressedKeyPattern = new boolean[4];
[Serializeable]
boolean[] keyPatterns = new boolean[];

void Update () {
    pressedKeyPattern[0] = Input.GetKey(KeyCode.Z);
    pressedKeyPattern[1] = Input.GetKey(KeyCode.X);
    pressedKeyPattern[2] = Input.GetKey(KeyCode.N);
    pressedKeyPattern[3] = Input.GetKey(KeyCode.M);

    if (pressedKeyPattern == keyPatterns[round]) {
          // success
    } else {
         // fail
    }
}

Then you can make it almost automatic and you can edit the rounds in the inspector. Now, you can make it more awesome and replace the numbers with enums, the array with something more descriptive if you want and improve the inspector also to make it easier to edit. Or you can load up the patterns from file or from the internet or whatever you want.
The point is, you don’t have to have only one key, you’re aiming for the pattern. You can have more challenges if you want.

You probably want to abstract Input, on a console you will be using buttons on gamepad and on keyboard keys.

If you have Commands you could use a combination of commands like Commands.Jump, Commands.Attack, etc as combo sequence. Store the sequences in Scriptable objects. Each frame iterate over all sequences. If one match store this one. Next frame only check against this one if next command mathes. If it matches progress to next command. If wrong command is pressed cancel.