Rebinding axis actions and return the binding of action

To those looking for a solution see my comment below.

How do you rebind and action that uses a 1D Axis?
I am able to rebind a normal binding using:

inputAction.map.action.ApplyBindingOverride("<Keyboard>/w")

but I can’t seem to figure out how to override the binding if its anything else but a normal binding

In my case the binding should look something like this:

inputAction.PlayerControls.Horizontal.ApplyBindingOverride("NameOfAxis", "PositiveBinding", "NegativeBinding");

in this case, the line above actually builds in the editor but then doesn’t do anything.

also while I’m at it how do I get back the current binding of an action?
say I just want to do something like this:

Binding = inputAction.map.action.binding;
Debug.Log(Binding);

any help is greatly appreciated, I’m usually pretty good and digging through forums to find solutions but I’ve had a real hard time finding anything to do with the new input system.

This is missing some nice wrapper APIs. Have made a note to add them.

ATM the binding indices have to be looked up manually.

var action = inputAction.PlayerControls.Horizontal;
var negative = action.bindings.IndexOf(b => b.name == "negative");
var positive = action.bindings.IndexOf(b => b.name == "positive");

action.ApplyBindingOverride(negative, "<Keyboard>/upArrow");
action.ApplyBindingOverride(positive, "<Keyboard>/downArrow");

Ok, this works great, but how would I set it up so I can change more than one axis in a binding?
for example:
5955329--638255--Screenshot from 2020-06-08 16-04-01.png

I have two axises setup for each direction (horizontal and vertical), one that is used for the keyboard and one for a gamepad. so when I use the code you gave me change the first pair of bindings (in this case the 1DAxis) but not the second pair (1DAxisController). so how do i change the second pairs?
also thank you for the quick reply.

Also is there a way to wait for a keypress and then get which key is pressed?
I’ve seen the PerformInteractiveRebinding() method but it doesn’t seem to be what I’m looking for, I want to wait for a keypress store the keycode of whatever key was pressed and then store it in a string like /w and then use the ApplyBindingOverride() method later.

Ok so for those of you looking for an answer out there, here’s the solution I came up with. I hope it saves you a headache and some research time.

If you want to rebind multiple axis bindings this is how you do it:
I discovered that everything under the axis action is considered a binding including the sub axis’s (in my case 1DAxis and 1DXAxisController as see in my comment above) so the order would go as follows:
0 1DXAxis
1 Negative: S [Keyboard]
2 Positive: W [Keyboard]
3 1DXAxisController
4 Negative: Left Stick/Down [Gamepad]
5 Positive: Left Stick/Up [Gamepad]

so the keyboard keys can be assigned as follows using the indexes 1 and 2:

//rebind vertical keyboard
inputAction.PlayerControls.Vertical.ApplyBindingOverride(1, k[1]);
inputAction.PlayerControls.Vertical.ApplyBindingOverride(2, k[0]);

//rebind horizontal keyboard
inputAction.PlayerControls.Horizontal.ApplyBindingOverride(1, k[2]);
inputAction.PlayerControls.Horizontal.ApplyBindingOverride(2, k[3]);

The k[ ] array being the keybind such as: /a

and for the controller, as follows using the indexes 4 and 5:

//rebind vertical controller
inputAction.PlayerControls.Vertical.ApplyBindingOverride(4, c[1]);
inputAction.PlayerControls.Vertical.ApplyBindingOverride(5, c[0]);

//rebind horizontal controller
inputAction.PlayerControls.Horizontal.ApplyBindingOverride(4, c[2]);
inputAction.PlayerControls.Horizontal.ApplyBindingOverride(5, c[3]);

The c[ ] array being the keybind such as: /eastButton

As for the second problem, what i did is just us the actionToRebind.PerformInteractiveRebinding() method to rebind an empty action called temp which isn’t ever used by the player and tell it within the rebind operation to pull the key string and assign it to another string also called temp:

public void ListenForKey(int ci)
    {
        inputAction.Disable();
        //Debug.Log($"'{inputAction.PlayerControls.Temp}'");
        RemapButtonClicked(inputAction.PlayerControls.Temp);
        inputAction.Enable();
    }

    public void RemapButtonClicked(InputAction actionToRebind)
    {
        var rebindOperation = actionToRebind.PerformInteractiveRebinding(0)
            .WithControlsExcluding("<Keyboard>/escape") //to prevent the player from re binding the pause key
            .WithControlsExcluding("<Gamepad>/select") //to prevent the player from re binding the pause key
           
            .WithControlsExcluding("<Pointer>/position") // Don't bind to mouse position
            .WithControlsExcluding("<Pointer>/delta"); // Don't bind to mouse movement deltas

        rebindOperation.OnComplete(
            operation =>
            {
                //Debug.Log($"Rebound '{actionToRebind}' to '{operation.selectedControl}'");
                temp = $"'{operation.selectedControl}'";

                temp = FormatKeyCode(temp);

                operation.Dispose();
            });
        rebindOperation.Start();
    }

the string will end up looking something like this: Key:/Keyboard/a
So I also wrote the FormatKeyCode() method to change the string to this format: /a which is the format used by the .ApplyBindingOverride() method, I doubt I’ve done it in the most efficient way but here it is anyway if you’re interested:

public string FormatKeyCode(string t)
    {
        int i = 0;
        string x = "";
        while(i < t.Length)
        {
            if(t[i] == ':')
            {
                x += "<";
                break;
            }
            i++;
        }

        i++;
        i++;
        while(i < t.Length)
        {
            if(t[i] == '/')
            {
                x += ">/";
                break;
            }
            x += t[i];
            i++;
        }

        i++;
        while(i < t.Length)
        {
            string j = "'";
            if(t[i] == j[0])
            {
                break;
            }
            x += t[i];
            i++;
        }
       
        return x;
    }

I then took the temp string, assigned to an array, and then bound it in another script when I needed to.

I hope this helps someone out there. If you have any questions let me know.

        public static string FormatKeyCode(string keyBinding)
        {
            //Input: Key:/Keyboard/a
            //Output: <Keyboard>/a
            var matches = Regex.Matches(keyBinding, @"^.*:/(.*)/(.*)$");
            if (matches.Count > 0 && matches[0].Groups.Count == 3)
                return $"<{matches[0].Groups[1].Value}>/{matches[0].Groups[2].Value}";
            return "";
        }