0
\$\begingroup\$

Good Morning All,

I am using Unity's New Input System. I have an Action Map created called 'Menu'.

Currently, this is how I check for specific button presses.

If( xxx.Menu.Select.WasPressedThisFrame() )
{
  // Do Stuff
}

The above works fine. However, now I need to check if any button was pressed from the Action Map.

For example, my game could show an image of a PS4's X Button. I need to detect if the player presses the right or wrong button. If the right button is pressed they win and if the wrong button is pressed they lose.

Hopefully this makes it even more clear:

If( METHOD THAT CHECKS IF ANY INPUT FROM THE MENU ACTION MAP WAS PRESSED ) // <- This is what I need
{
      If( xxx.Menu.Select.WasPressedThisFrame() )
      {
        // You win!
      }

      Else
      {
        // You Lose!
      }
}

To summarize, I'm looking for a method from Unity's New Input System that checks if any button was pressed. Thank you so much for taking the time!😊

\$\endgroup\$
4
  • \$\begingroup\$ How big is the set of buttons? All keyboard keys or are we talking about a small subset of them or a controller? An action map seems the wrong way, since you do not want to bind actions in this case. But the new input system still allows you to read the values: docs.unity3d.com/Packages/[email protected]/manual/… \$\endgroup\$
    – Zibelas
    Sep 27, 2023 at 15:54
  • \$\begingroup\$ Thanks for the response @Zibelas! I'm a bit confused with why you think an Action Map seems wrong. The reason that I use an Action Map is so that the player can use whatever controller they prefer. So whether they use a PS4 Controller and hit 'X' or press the space bar on their keyboard, both can be mapped to 'Select'. That being said, I don't think the provided documentation solves my issue unfortunately. \$\endgroup\$ Sep 27, 2023 at 16:11
  • \$\begingroup\$ Because an action map represents a direct action. Press X to jump, press square to fire, not that you are checking in the jump method call if you press the fire square. \$\endgroup\$
    – Zibelas
    Sep 27, 2023 at 16:19
  • \$\begingroup\$ Good to hear! Glad you found it helpful. \$\endgroup\$
    – PepeOjeda
    Sep 30, 2023 at 15:57

2 Answers 2

1
\$\begingroup\$

You could use a setup like this : enter image description here

And then check with:

if (inputActions.actionMap.TestAction.WasPressedThisFrame())
{
    if (inputActions.actionMap.Good.WasPressedThisFrame())
    {
        Debug.Log("You win!");
    }
    else if (inputActions.actionMap.Bad.WasPressedThisFrame())
    {
        Debug.Log("You lose!");
    }
}

But, in general, with the new Input System it might make more sense to organize the input logic by using callbacks, rather than polling. Like this:

inputActions.actionMap.Good.performed += () =>
{
    Debug.Log("You win!");
}
inputActions.actionMap.Bad.performed += () =>
{
    Debug.Log("You lose!");
}
\$\endgroup\$
3
  • \$\begingroup\$ Thanks for the reply, @PepeOjeda! The first half of your answer is honestly a great idea. I will probably end up using it if there is no method that looks for /any/ input. Though, I'd be pretty surprised and disappointed if the New Input System doesn't have a method to do that. As for the second half, using callbacks is not very convenient in my game. The good/bad buttons change too frequently based on mini-games. \$\endgroup\$ Sep 27, 2023 at 17:34
  • 1
    \$\begingroup\$ That's fair enough. You can rebind the actions at runtime through code, though, so maybe that's something worth looking into? \$\endgroup\$
    – PepeOjeda
    Sep 27, 2023 at 19:16
  • \$\begingroup\$ Just closing the loop to let you know I ended up using your solution. Having a specific Action for "Any" button being pressed seemed to work fine and is the best solution I've seen. Thanks again, @PepeOjeda. Really great solution! I'll probably make a separate thread inquiring about rebinding actions at runtime like you mentioned. \$\endgroup\$ Sep 29, 2023 at 17:25
3
\$\begingroup\$

Here is an example how you can check for any InputAction being triggered in any or specific InputActionMap:

using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;

public class TestAnyButton : MonoBehaviour
{
    [SerializeField] private InputActionAsset iaa;

    void Start()
    {
        iaa.Enable();
    }

    void Update()
    {
        if (iaa.Any((ia) => ia.WasPressedThisFrame()))
        {
            Debug.Log("Any action", this);
        }


        if (iaa.FindActionMap("AcitonMapName").Any((ia) => ia.WasPressedThisFrame()))
        {
            Debug.Log("Any action in an action map", this);
        }
    }
}

An alternative way is to subscribe to all the InputActions in a map:

public class TestAnyButton : MonoBehaviour
{
    [SerializeField] private InputActionAsset iaa;

    private InputActionMap observedMap;

    void OnEnable()
    {
        iaa.Enable();

        observedMap = iaa.FindActionMap("ActionMapName");
        foreach (var inputAction in observedMap)
        {
            inputAction.started += OnStarted;
        }
    }

    void OnDisable()
    {
        foreach (var inputAction in observedMap)
        {
            inputAction.started -= OnStarted;
        }
    }

    void OnStarted(CallbackContext context)
    {
        if (context.started)
        {
            Debug.Log($"{context.action.name} started.", this);
        }
    }
}
\$\endgroup\$

You must log in to answer this question.

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