Input System: How do I get the key/button associated to Cancel[any]?

Hello, im trying to do an automatic tooltip system where you give the action and it splits interaction, button, action name, and considers if using controller or keyboard to give something similar to “Hold LeftShoulder to aim”.

I wanted to do this system globally (that processes any binding you can put in the InputAction), but for the UI control scheme, as im using the Cancel [any], and Submit[any], the best i can get for those is the path “*/{Cancel}”.

What im trying to achieve is to get for example in Cancel button: for Switch gamepad (Button South), For Playstation and Xbox controllers (Button East).

I can get this behaviour if I put the desired button to be canceled, but in that case the switch and xbox cancel wouldn’t be different, and i wanted to keep that “automatic” behaviour.

Actually what i have to get the binding name and translate it to “button south” instead of “X” is

InputControlPath.ToHumanReadableString(currentActionMap.action.bindings[currentActionMap.action.GetBindingIndexForControl(currentActionMap.action.controls[0])].effectivePath, InputControlPath.HumanReadableStringOptions.OmitDevice);

worth mentioning: i dont know if its a bug, but using left click for a binding gives index -1 in GetBindingIndexForControl().

I tried different combinations and methods to try get a string for the active controller that matched what im searching for but it either was empty, or it was the path mentioned above ( “*/{Cancel}” )

EDIT: about the index -1, it seems that it occurs in more scenarios, not only in left click. As i was writting the info about this problem I tought it hadn’t anything to do with repeated bindings, but it seems it does.
Lets say the Gameplay layer is first and the UI layer is second. If an action qith the binding in Q is set for both, the second in order will get index -1…
I will investigate a little bit more about this. Seems weird to me because im passing the action, the controller, the index… The system shouldnt be confused to such point it thinks there’s no binding to that action.

--------------------SEE EDIT BELOW-----------------

Okay, so i think i finally solved the two problems.
Starting from the index problem I tried with some Debug.Log() and different methods from InputActionReference to get a string where the button asociated is the correct one.

The cleanest ones i got were .path and .tostring. Parsed with :


I get everything i wanted.

Also, I warn about this: if you use the Submit [Any] and want to display another key/button that is also asigned (for example: Spacebar instead of Enter), you have to put the [Any] Binding at the bottom of the action.

So an effective way to get the things done would be with this code:


     // currenAction map is an InputActionReference
     var control = currentActionMap.action.controls[0];

     //Get the button binded to the given action. Translated in gamepad to a global scheme. 
     //Ex: Button South intead of X or B

     string buttonName = InputControlPath.ToHumanReadableString(control.path, InputControlPath.HumanReadableStringOptions.OmitDevice);

    //This segment fixes the first letter being lowercase
    // leftShift >> LeftShift
        if (!String.IsNullOrEmpty(buttonName))
        buttonName = string.Concat(buttonName[0].ToString().ToUpper(), buttonName.Substring(1));

This code gets the generic name: for gamepads it returns “ButtonSouth” for example. If you use a combined approach to get this strings, it would give weird results. In the main question, the code I provide gives “Button South”, with spaces. take that in consideration.

To solve this problem, after all the code use the next one to add spaces between capital letters

        buttonName = Regex.Replace(buttonName, "([a-z])([A-Z])", "$1 $2");

It seems that while i was testing if the [Any] binding gets also gamepads, it turns out the bindings had an specific button assigned for the action, it wasn’t taking the automatic path I wanted.
In keyboard it works fine, but when i try to get the button for a controller I get a null exception in currentActionMap.action.controls[0];…

At this point I think i cant get the automathic behaviour I want, and is more straight forward for players to have the same placing for the cancel/submit in controllers no matter if they are using nintendo’s or xbox’s.

I unmarked this answer as valid, I will try to get it working, and update the info if I manage to do it, and open again to other users to find the correct answer.