Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Question Rebinding axis actions and return the binding of action

Discussion in 'Input System' started by Jared_Brian_, Jun 8, 2020.

  1. Jared_Brian_

    Jared_Brian_

    Joined:
    Feb 27, 2016
    Posts:
    16
    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:
    Code (CSharp):
    1. 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:
    Code (CSharp):
    1. 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:
    Code (CSharp):
    1. Binding = inputAction.map.action.binding;
    2. 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.
     
    Last edited: Jun 17, 2020
  2. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    This is missing some nice wrapper APIs. Have made a note to add them.

    ATM the binding indices have to be looked up manually.

    Code (CSharp):
    1. var action = inputAction.PlayerControls.Horizontal;
    2. var negative = action.bindings.IndexOf(b => b.name == "negative");
    3. var positive = action.bindings.IndexOf(b => b.name == "positive");
    4.  
    5. action.ApplyBindingOverride(negative, "<Keyboard>/upArrow");
    6. action.ApplyBindingOverride(positive, "<Keyboard>/downArrow");
     
  3. Jared_Brian_

    Jared_Brian_

    Joined:
    Feb 27, 2016
    Posts:
    16
    Ok, this works great, but how would I set it up so I can change more than one axis in a binding?
    for example:
    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.
     
    Last edited: Jun 9, 2020
  4. Jared_Brian_

    Jared_Brian_

    Joined:
    Feb 27, 2016
    Posts:
    16
    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 <keyboard>/w and then use the ApplyBindingOverride() method later.
     
  5. Jared_Brian_

    Jared_Brian_

    Joined:
    Feb 27, 2016
    Posts:
    16
    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:
    Code (CSharp):
    1. //rebind vertical keyboard
    2. inputAction.PlayerControls.Vertical.ApplyBindingOverride(1, k[1]);
    3. inputAction.PlayerControls.Vertical.ApplyBindingOverride(2, k[0]);
    4.  
    5. //rebind horizontal keyboard
    6. inputAction.PlayerControls.Horizontal.ApplyBindingOverride(1, k[2]);
    7. inputAction.PlayerControls.Horizontal.ApplyBindingOverride(2, k[3]);
    The k[] array being the keybind such as: <Keyboard>/a

    and for the controller, as follows using the indexes 4 and 5:
    Code (CSharp):
    1. //rebind vertical controller
    2. inputAction.PlayerControls.Vertical.ApplyBindingOverride(4, c[1]);
    3. inputAction.PlayerControls.Vertical.ApplyBindingOverride(5, c[0]);
    4.  
    5. //rebind horizontal controller
    6. inputAction.PlayerControls.Horizontal.ApplyBindingOverride(4, c[2]);
    7. inputAction.PlayerControls.Horizontal.ApplyBindingOverride(5, c[3]);
    The c[] array being the keybind such as: <Gamepad>/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:

    Code (CSharp):
    1.  
    2. public void ListenForKey(int ci)
    3.     {
    4.         inputAction.Disable();
    5.         //Debug.Log($"'{inputAction.PlayerControls.Temp}'");
    6.         RemapButtonClicked(inputAction.PlayerControls.Temp);
    7.         inputAction.Enable();
    8.     }
    9.  
    10.     public void RemapButtonClicked(InputAction actionToRebind)
    11.     {
    12.         var rebindOperation = actionToRebind.PerformInteractiveRebinding(0)
    13.             .WithControlsExcluding("<Keyboard>/escape") //to prevent the player from re binding the pause key
    14.             .WithControlsExcluding("<Gamepad>/select") //to prevent the player from re binding the pause key
    15.            
    16.             .WithControlsExcluding("<Pointer>/position") // Don't bind to mouse position
    17.             .WithControlsExcluding("<Pointer>/delta"); // Don't bind to mouse movement deltas
    18.  
    19.         rebindOperation.OnComplete(
    20.             operation =>
    21.             {
    22.                 //Debug.Log($"Rebound '{actionToRebind}' to '{operation.selectedControl}'");
    23.                 temp = $"'{operation.selectedControl}'";
    24.  
    25.                 temp = FormatKeyCode(temp);
    26.  
    27.                 operation.Dispose();
    28.             });
    29.         rebindOperation.Start();
    30.     }
    31.  
    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: <Keyboard>/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:

    Code (CSharp):
    1.  
    2. public string FormatKeyCode(string t)
    3.     {
    4.         int i = 0;
    5.         string x = "";
    6.         while(i < t.Length)
    7.         {
    8.             if(t[i] == ':')
    9.             {
    10.                 x += "<";
    11.                 break;
    12.             }
    13.             i++;
    14.         }
    15.  
    16.         i++;
    17.         i++;
    18.         while(i < t.Length)
    19.         {
    20.             if(t[i] == '/')
    21.             {
    22.                 x += ">/";
    23.                 break;
    24.             }
    25.             x += t[i];
    26.             i++;
    27.         }
    28.  
    29.         i++;
    30.         while(i < t.Length)
    31.         {
    32.             string j = "'";
    33.             if(t[i] == j[0])
    34.             {
    35.                 break;
    36.             }
    37.             x += t[i];
    38.             i++;
    39.         }
    40.        
    41.         return x;
    42.     }
    43.  
    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.
     
  6. Code (CSharp):
    1.         public static string FormatKeyCode(string keyBinding)
    2.         {
    3.             //Input: Key:/Keyboard/a
    4.             //Output: <Keyboard>/a
    5.             var matches = Regex.Matches(keyBinding, @"^.*:/(.*)/(.*)$");
    6.             if (matches.Count > 0 && matches[0].Groups.Count == 3)
    7.                 return $"<{matches[0].Groups[1].Value}>/{matches[0].Groups[2].Value}";
    8.             return "";
    9.         }
    10.  
     
    Last edited by a moderator: Jun 17, 2020