0
\$\begingroup\$

Good Afternoon,

I'd like to incorporate a button-matching minigame into my game. I have an InputActionMap made specifically for this minigame. One of the buttons from the 'Any' InputAction will be chosen randomly as the 'correct' button. An image of the chosen button will display on the screen and the player will need to press the matching button on their gamepad.

enter image description here

I need to be able to tell when the player presses one of the 'Any' buttons, and if it was the correct button or not. If the player presses the correct button, they win. If they press a button and its not the correct button, they lose.

\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I would implement this like so:

Create a MinigameActions input map with 4 distinct buttons - not all lumped into one "Any" button. Something like:

  • MinigameActionA
  • MinigameActionB
  • MinigameActionC
  • MinigameActionD

You can default these to north/east/south/west face buttons, and in your options menu, you can let players remap them to other controls if they like (e.g. for accessibility controllers).

We'll make each one correspond to an enum value, and also make an enum for the results from pressing them:

public enum MinigameAction {
    A, B, C, D
}

public enum MinigameActionResult {
    Correct,
    Incorrect,
    Neutral // Use for buttons you want to ignore / not mark "wrong".
}

Then we can define a parent type for your minigame-specific gameplay scripts:

public abstract class Minigame : MonoBehaviour {
    MinigameActionResult PerformAction(MinigameAction action);
}

A button combo matching minigame script could then look like this:

public ButtonComboMatch : Minigame {

    public List<List<MinigameAction> comboSequence;

    int _currentCombo;
    int _placeInCombo;

    public MinigamActionResult PerformAction(MinigamAction action) {
        if (comboSequence[_currentCombo][_placeInCombo] != action) {
            // Trigger combo broken feedback, then rewind to the start of the combo.
            _placeInCombo = 0;
            return MinigameActionResult.Incorrect;
        }

        // Otherwise, correct! Advance to the next button to press.
        if(++_placeInCombo == comboSequence[_currentCombo].Count) {
            // Finished the current combo - trigger success fanfare and advance.
            if (++_currentCombo == comboSequence.Count) {
                // Finished final combo - you win!
                // TODO: trigger victory.
            }

            _placeInCombo = 0;
        }

        return MinigameActionResult.Correct;
    }
}

Your input script can then take a reference to the current Minigame gameplay script, and relay button presses to it:

Minigame _currentMinigame;

void RelayAction(MinigameAction action) {
    var result = _currentMinigame.PerformAction(action)
    switch (result) {
       case MinigameActionResult.Correct:
           // Do any common "on correct action" feedback here.
           break;
       case MinigameActionResult.Incorrect:
           // Do any common "on action incorrect" feedback here.
           break;
    }
}

void SetupActions(ActionMap actionMap) {
    actionMap.MinigameActionA.performed += () => RelayAction(MinigameAction.A);
    actionMap.MinigameActionB.performed += () => RelayAction(MinigameAction.B);
    actionMap.MinigameActionC.performed += () => RelayAction(MinigameAction.C);
    actionMap.MinigameActionD.performed += () => RelayAction(MinigameAction.D);
}

In this way, the script that talks directly to the input system has only one job: report which button was pressed.

Categorizing that press as either correct or incorrect is the job of the minigame script, and you can swap those out without touching anything in the input system.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .