Search Unity

Rebinding Keys Isn't reflected in existing controlSchemes

Discussion in 'Input System' started by ZachariBarnes, Feb 15, 2020.

  1. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    I've been working to migrate my game to the new Input system in order to have the ability to allow the players to Rebind all all the controls in my game, including existing axis(Vertical, Horizontal, ect...)
    I've created my Input actions and configured them they way I believe they need to be configured.
    upload_2020-2-15_16-58-49.png upload_2020-2-15_16-59-22.png

    And I've written code that allows me to read the inputs and react to them.

    Code (CSharp):
    1. public class GameController : MonoBehaviour
    2. {
    3.   public InputMaster controls;
    4.     bool pausePressed, deselectPressed, resetCameraPressed, restartPressed;
    5.  
    6.     public void Awake()
    7.     {
    8.         controls = new InputMaster();
    9.         if (PlayerPrefs.HasKey("Controls"))
    10.         {
    11.             string controlsJSON = PlayerPrefs.GetString("Controls");
    12.             controls.asset.LoadFromJson(controlsJSON);
    13.         }
    14.         controls.GameplayControls.Pause.performed += ctx => pausePressed = !pausePressed;
    15.         controls.GameplayControls.Deselect.performed += ctx => deselectPressed = !deselectPressed;
    16.         controls.GameplayControls.ResetCamera.performed += ctx => resetCameraPressed = !resetCameraPressed;
    17.         controls.GameplayControls.Restart.performed += ctx => restartPressed = !restartPressed;
    18.  
    19.     }
    20.  
    21.     private void OnEnable()
    22.     {
    23.         controls.Enable();
    24.     }
    25.  
    26.     private void OnDisable()
    27.     {
    28.         controls.Disable();
    29.     }
    30. }
    31.  
    32.    public class RTS_Camera : MonoBehaviour
    33.     {
    34.         public InputMaster controls;
    35.         Vector2 movement;
    36.         Mouse mouse;
    37.         float mouseZoom;
    38.         float screenWidth;
    39.         float screenHeight;
    40.         Vector2 center;
    41.         float rotationInput;
    42.         int zoomInput;
    43.         private void Awake()
    44.         {
    45.  
    46.             controls = new InputMaster();
    47.             controls.CameraMovementControls.Movement.performed += ctx => movement = ctx.ReadValue<Vector2>();
    48.             controls.CameraMovementControls.Rotate.performed += ctx => rotationInput = ctx.ReadValue<float>();
    49.             controls.CameraMovementControls.Zoom.performed += ctx => zoomInput = Mathf.RoundToInt(ctx.ReadValue<float>());
    50.             mouse = Mouse.current;
    51.             mouseZoom = mouse.scroll.y.ReadValue();
    52.             screenWidth = Screen.width;
    53.             screenHeight = Screen.height;
    54.             center = new Vector2(screenWidth / 2, screenHeight / 2);
    55.         }
    56.         private void OnEnable()
    57.         {
    58.             controls.Enable();
    59.         }
    60.  
    61.         private void OnDisable()
    62.         {
    63.             controls.Disable();
    64.         }
    65. }
    66.  
    That all works as I would expect, However when I Rebind the controls Using the "Rebind Action UI" script (Transplanted into my project from the "Rebinding UI" Sample) the "ActionBindingText" Updates with the new controls but my Existing 'InputMaster' Objects still only respond to the original controls. This is my primary issue right now.

    My end goal is to allow users to rebind controls and have those controls persist across plays (and between closing and reopening the game.)
    The secondary issue I am having is that I have no idea how to "Save" the binds once they are set but I am assuming I'll need to save off the .asset JSON and load based on the saved JSON. Is that the correct line of thinking?

    I've been banging my head against this for quite awhile and I would appreciate any help you can provide.
    Thanks
    -Zachari Barnes
     
  2. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    I've also Used the Input Debugger and It doesn't appear that anything was remapped, but I don't think overrides show on the Input Debugger by default.
     
  3. bilbaeno

    bilbaeno

    Joined:
    Dec 13, 2012
    Posts:
    4
    I am having the same issue at the moment. I am using the RebindActionUI script from the sample, and it is updating the labels for the bindings, but the Actions and Bindings never seem to be modified. It is the same for the sample scene in the sample.
     
    GhostStreetGuru likes this.
  4. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    @bilbaeno I'm seeing the same thing as you.
    I'm on Unity 2019.2.11.f1

    Could that be when it isn't carrying the keybinding all the way into gameplay?
     
  5. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    @Rene-Damm any thoughts? are we just missing a step here?
     
  6. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    upload_2020-3-2_23-26-18.png

    I have not set up any specific control schemes. Would that break the rebinding process in a way that doesnt throw an error code?
     
  7. bilbaeno

    bilbaeno

    Joined:
    Dec 13, 2012
    Posts:
    4
    From what I've learned it isn't supposed to change the actual binding in the asset, just set an override path for the binding.

    But even so, I am not receiving input from the override binding.
     
    tigerleapgorge likes this.
  8. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    Yeah same.

    I've been throwing in debug strings and when I throw them in OnActionChange in RebindActionUI.cs to try and expose the name for the action, I get null reference errors.
    upload_2020-3-3_20-19-58.png

    (pic of the error coming after my session loads)
     
  9. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
  10. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    I made a control scheme but that broke more things in my game and didnt fix the rebind not applying the override. Poking around the RebindActionUI.cs file i tried to find a place to plug in ApplyBindingOverride() but i can't get all the info i need to pass along. Any one been able to figure this out?

    upload_2020-3-4_23-55-32.png
     
    tigerleapgorge likes this.
  11. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    tigerleapgorge and ZachariBarnes like this.
  12. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Sorry for my lateness here.

    So, one general thing, with the C# generated wrappers, control schemes won't do anything except with additional scripting. This is a gotcha that has caught many users unawares and something I would urgently like to have fixed after 1.0. Basically, whereas PlayerInput automatically takes care of device pairing and control scheme selection, you get none of this ATM with generated C# wrappers. Means that all bindings are active no matter what. You need to manually hook up that part.

    Code (CSharp):
    1. var controls = new InputMaster();
    2.  
    3. // Restrict the controls to certain devices.
    4. controls.devices = new InputDevice[] { Keyboard.current, Mouse.current };
    5.  
    6. // Restrict the controls to one control scheme.
    7. controls.bindingGroup = InputBinding.MaskByGroup(controls.controlSchemes.First(x => x.name == "Keyboard&Mouse").bindingGroup);
    Not pretty and not convenient. On the list for improvement.

    Finally, we have an open bug where ApplyBindingOverride does not correctly flush out state on actions and old controls end up sticking around. I've started looking into it and a fix is expected to land in the next package after 1.0.0-preview.6. My suspicion is that this may be what you're running into here.

    As for saving rebinds, we have adding some more convenient wrappers on this on the list for after 1.0. I've posted about how to manually do this here.
     
    tigerleapgorge and ZachariBarnes like this.
  13. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    Thank you for the info drop, @Rene-Damm

    So does the RebindActionUI prefab actually call ApplyBindingOverride in its current iteration and it is just failing to flush old controls out?

    or is there an insertion point where that function needs to be added?
     
    ZachariBarnes likes this.
  14. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    @Rene-Damm

    For reference:
    Issue occurs as detailed above on 1.0.0-preview.6
     
    ZachariBarnes likes this.
  15. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    @Rene-Damm bumping this to see if the potential fix for rebinding UI successfully impacting the player at runtime is slated to be included in the next update? Between the rebinding action UI prefab, the control binding Ui prefab in the tank demo scene, and a UI of my own I have not been able to apply a binding override so far. This would be a huge plus to get this on the next update (which hopefully is not delayed)
     
    ZachariBarnes likes this.
  16. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Having a look. Will get back to you.
     
  17. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    @Rene-Damm any luck so far?
     
  18. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    Sorry to poke so much, @Rene-Damm
    Any timeline on a fix for this? I just can't figure out why none of my solutions work for this problem. I'd already used the Rebinding UI prefab provided in the Package Manager to set up my rebinding screen, so overcoming the hump of "I bind something, it updates the UI, but my controls dont effectively change for the player" would just make this who feature fall into place. Please save me <3 I've been blocked on this feature for a month now
     
    ZachariBarnes likes this.
  19. ItsTwelveOclock

    ItsTwelveOclock

    Joined:
    May 28, 2017
    Posts:
    25
    I have the same issue. The RebindUI sample scene doesn't seem to actually rebind anything. @Rene-Damm should we just go back to using the old input system for the time being? Any estimate on when updates to the input system will be coming? I have other issues such as InputAction.performed or InputAction.cancelled not being fired OnButtonRelease after rebinding which could be related.
     
    ZachariBarnes likes this.
  20. abdo400

    abdo400

    Joined:
    Feb 12, 2016
    Posts:
    44
    Adding the code in UpdateBindingDisplay() logged me the new override path, but it still didn't trigger any action with the new key binding. The old key binding still works...

    upload_2020-4-15_17-44-3.png
     
  21. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    @Rene-Damm to follow up, newest update to the input system and it’s prefabs (.7 preview) does not resolve the issue
     
    ZachariBarnes likes this.
  22. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    Yeah still having the same issue. I also tried the code suggested to set the binding group but the new control still doesn't work and the old one does. Is there an ETA on this fix? This feature request has been blocked in my game since January because of this...
     
  23. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    GENTLEMEN, WHERE I WAS TOO DUMB TO UNDERSTAND BEFORE, NO MOOORE!

    @Rene-Damm actually gave me the solution and i didn't realize it. upload_2020-5-8_1-24-51.png

    Here is a sample of what I had been using. My input action was named NewControls so I had built this into each script that needed to hear player input. This was utilizing the C# Generated Wrapper that Rene was talking about. I also had a PlayerInput component on my game object that was set to call C# events.

    This was wrong.

    Solution:
    In order to make the RebindActionUI prefab function, I had to set the PlayerInput component to call Unity Events, and then manually link the events. I had to remove everything in the red box above as well as the "NewControls.IShooterActions" from the top line in the picture above. Then I left all of my OnMove/OnShoot/OnSubmit/etc. methods in my script and instead of the wrapper (variable "controls" in the picture above) calling them, i manually linked them to the unity events in the PlayerInput component in the inspector.

    After that, my keybindings started to fall into place. The other gotcha I ran into was that my "Input System UI Input Module" component with the EventSystem had been using actions from the same action map that I had setup rebinding elements for. This rendered them as "enabled" even when the PlayerInput module was disabled. If you have an action map for "In Game Events" then you'll want another action map for "UI Interactions" and have those actions in the "Input System UI Input Module". So you can disable your PlayerInput component as you enter the rebinding menu, use the "UI Interactions" action map to continue to navigate around and interact with the rebinding ui, and then re-enable your PlayerInput component as you exit the rebinding menu.
     
  24. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
  25. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    Thanks I'll try this out sometime this week I hope!
     
  26. skeptika

    skeptika

    Joined:
    Dec 31, 2011
    Posts:
    108
    Was this ever resolved? I tried using the Rebinding UI example and prefab, and while it does update the new binding in the UI, it does not actually rebind (at runtime). I couldn't follow Ghosts proposed solution at all. Has anyone gotten the Rebinding UI example/prefab to actually rebind at runtime?

    Video is Renee showing the example and prefab that I'm referring to:
     
  27. GhostStreetGuru

    GhostStreetGuru

    Joined:
    Dec 4, 2016
    Posts:
    16
    How are you attaching a PlayerInput component or C# class to your object?
     
  28. skeptika

    skeptika

    Joined:
    Dec 31, 2011
    Posts:
    108
    I did precisely what the video suggests, which is take the prefab he built and the scripts he included, and simply reconnect it to my Player Controls (and yes I override the prefab to my values).



    The button itself uses his script to actually perform the binding.



    It does work, in the same sense that his example works, I see it update the UI with the new key for rebinding, however it does not change the underlying controls. Note: his provided scene ALSO doesn't seem to update his controls, it literally only changes the UI. It seems very bizarre to me to release an official sample called Rebinding Sample that doesn't actually rebind (even at runtime)?

    It's using entirely his code, nothing custom. The only thing "custom" is the references themselves to my player controls via the inspector.
     
    Last edited: Jul 13, 2020
    maxmitchelll and ZachariBarnes like this.
  29. Shaelle

    Shaelle

    Joined:
    Nov 19, 2018
    Posts:
    9
    I had the same issue, and this video
    given me the hint to solution. Manuals I have seen before used the following approach: after you created PlayerControls asset, you used it to generate C# class, and created scripts like

    public PlayerControls controls;

    ...

    controls = new PlayerControls();

    controls.Input.Interact.performed += ctx => Interact();

    The thing is: you do not need it now. What you do need, is to add to the game object (where you controls should be) component called "Player Input". In it, you must setup Actions and Default Map (which should be the same as on the buttons you using to change keybindings).

    When you can select behaviour. If you using "Send messages", it will show you list of messages this component generates based on you input, and all you have to do, is to create in a script attached to the same gameoject method with the same name as in the list. For example, I have action called "Interact" and I see that among the messages list there is "OnInteract". So I just create in the script following method:

    public void OnInteract()
    {
    Debug.Log("Interacting");
    }

    Last, but not least: you have to disable action map before you can rebind it. In my experimental project, I am using following code (attached to a three buttons on UI) for manually turn it on or off:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.InputSystem;

    public class ToogleInput : MonoBehaviour
    {

    public PlayerInput playerController;

    private InputActionMap actionMap;


    // Start is called before the first frame update
    void Start()
    {
    actionMap = playerController.actions.FindActionMap("Input");
    }


    public void On()
    {
    actionMap.Enable();

    Check();
    }

    public void Off()
    {
    actionMap.Disable();

    Check();
    }


    public void Check()
    {
    if (actionMap.enabled) { Debug.Log(" action map enabled"); }
    else { Debug.Log(" action map disabled"); }
    }
    }

    Of course in real project you have to do it automatically (and do checks for assignments etc.).
     
  30. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    To update On this I have attempted all the things explained in the above posts, I have added the player Input component and attempted a rebind. It failed due to the action map being enabled so I added an enable and disable to the Interactive rebind. Code to follow

    public void StartInteractiveRebind()
    {
    if (!ResolveActionAndBinding(out var action, out var bindingIndex))
    return;

    action.actionMap.Disable();
    // If the binding is a composite, we need to rebind each part in turn.
    if (action.bindings[bindingIndex].isComposite)
    {
    var firstPartIndex = bindingIndex + 1;
    if (firstPartIndex < action.bindings.Count && action.bindings[firstPartIndex].isPartOfComposite)
    PerformInteractiveRebind(action, firstPartIndex, allCompositeParts: true);
    }
    else
    {
    PerformInteractiveRebind(action, bindingIndex);
    }
    action.actionMap.Enable();
    }

    However once again this only updates the UI to display the new key but the game does not respond to the input at all. I really don't think it can be said better than this:

    @Rene-Damm is there any update on this at all? This Issue has been open since Feb 15. It'll be 6 months in 10 days...
    @GhostStreetGuru did you ever get this resolved in your experiments?
     
  31. RaoulWB

    RaoulWB

    Joined:
    Feb 9, 2014
    Posts:
    14
    As I'm trying to get an Input rebinder to work for my game, I ended up doing everything mentioned in the previous posts with no luck.

    Only useful thing I could add is that both with or without enabling/disabling the actions and action map on rebind, this is what the Input Debug window shows me:

    Before doing any rebinding
    upload_2020-8-7_17-46-12.png

    After having rebound an action called "Jump".
    A new action with the same name seems to have been created?
    upload_2020-8-7_17-48-14.png

    This third "Jump" action is correctly rebound to the button I pressed ("enter" in this case). As all of you reported so far, the UI also correctly shows the new input binding (which, again, is the "enter" key).

    I'm not particularly expert of the Input Debugger, but the apparent creation of a new action instead of modifying the existing ones could be a good lead to understand what's wrong?


    Btw, in case anyone wonders, the actions being doubled by default should be unrelated to this input rebinding matter: a second copy of each action appears the moment the Input Action Asset of choice gets enabled. I can also add that no additional copies of the actions get created if you were to Enable() it multiple times, nor if you happen to both call Enable() and Disable() back and forth at any point.

    Addendum:
    If I keep rebinding this jump action, no more copies of the action get created, but instead this "third instance" of the action just keeps changing according to what I'm pressing.
    upload_2020-8-7_18-10-58.png

    Effectively, the "third instance" always shows exactly what is shown in the UI.


    The more I keep inspecting this, the more likely it seems that this a good element to check.
     

    Attached Files:

    pantang and ZachariBarnes like this.
  32. itsnottme

    itsnottme

    Joined:
    Mar 8, 2017
    Posts:
    129
    Was anyone able to get this working?
    I did some testing and changing the binding directly from the InputActions works as expected, but doesn't work when using InputActionReference as used in the Input System rebinding example.
     
    ZachariBarnes likes this.
  33. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    No I still have a non-functioning input binder in my game. At this rate it looks I'm shipping without the ability to rebind keys.
    I wish I was more active on this forum so I would know who to ping for help. @Rene-Damm hasn't responded to this thread in many months.
     
  34. itsnottme

    itsnottme

    Joined:
    Mar 8, 2017
    Posts:
    129
    I found a solution, but it's not pretty.

    controls is the class I create the InputActions in. You have to make sure, you use the same InputActions you use for the input controls in the game.

    Code (CSharp):
    1. foreach (var map in controls.inputs.asset.actionMaps)
    2.             {
    3.                 foreach (var tempAction in map.actions)
    4.                 {
    5.                     if (tempAction.name == m_Action.action.name)
    6.                     {
    7.                         inputAction = tempAction;
    8.                         break;
    9.                     }
    10.                 }
    11.                 if (inputAction != null)
    12.                 {
    13.                     break;
    14.                 }
    15.             }
     
    pantang likes this.
  35. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    @ItsNotme
    That's great, Where are you running this code? In the rebind action?
    Also are you using a Player Input component?
    Thanks
     
  36. itsnottme

    itsnottme

    Joined:
    Mar 8, 2017
    Posts:
    129
    Yes in rebind action.
    No, I just create an object of InputActions.
     
  37. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    How did you import your class into the
    Code (CSharp):
    1. RebindActionUI
    class? Whenever I try I get a "Type or Namespace name could not be found" Error and it wont compile. @ItsNotme
    Also What are you doing with the inputaction and where does it come from?
    Can you show all the code for the method it is in? I think that would help me.
     
    Last edited: Nov 16, 2020
  38. Vagabond_

    Vagabond_

    Joined:
    Aug 26, 2014
    Posts:
    1,148
    Hi,

    do you guys still have this issue. I am able to change/save/load overrides but the new overridden bindings are not respected. Still getting input only from bindings set in the editor. I am using latest InputSystem v1.0.1.0

    Is this still broken !?
     
    ZachariBarnes likes this.
  39. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    Has anyone got this working? Id happily pay a couple quid on the asset store for basic character controller example that can open a ui and rebind the actions. Bonus points for a Disco theme.
     
    ZachariBarnes likes this.
  40. ZachariBarnes

    ZachariBarnes

    Joined:
    Nov 6, 2017
    Posts:
    12
    @Vagabond_ @pantang
    I have not gotten this working yet. I am shipping by game next month so I'm just sending it without the ability to rebind keys. I too would love to see a working version of this. Right now this whole experience has left a really bad taste in my mouth. The fact this thread has been continuously ignored by the Unity Team makes me feel like they routinely ship broken features and don't really care about the people who use them. I switched to the new input system because I was told the old one would not allow for rebinding keys, In reality it seems like Unity does not allow rebinding keys at all out of the box and you have to build your own input system if you want this functionality. I'm extremely grateful for everyone who tried to help fix this problem but unfortunately I've given up hope on finding an answer here. Maybe We should try Stack Overflow or look for an existing asset on the store for this feature.
     
  41. pantang

    pantang

    Joined:
    Sep 1, 2016
    Posts:
    219
    It really does suck but in their defence it is a preview feature so kind of our own faults for going with this solution. Do hope someone comes up with an example soon though, this puzzles been bugging me for ages.
     
  42. jimmosio

    jimmosio

    Joined:
    Dec 25, 2018
    Posts:
    1
    @ZachariBarnes @pantang @Vagabond_
    I'm going to necro this post, for a good cause at least I think. I managed to get remappable bindings working. I used @itsnottme 's code, along with other things. Don't know if they'll be relevant, but part of having the whole system working was reading these threads: 1 2 . I'll just focus on what you need for the remappable keybinds, if you're not familiar with some methods I'm using check those two threads out.

    I have a
    SettingsManager
    singleton (which will be
    SettingsManager.Instance
    from now on), to which I assign my InputActionAsset:
    Code (CSharp):
    1. public InputActionAsset control;
    The component that I use on my buttons to change keybinds has the following, here itsnottme's code comes into play. I never use the unity asset's input actions, aside from assigning
    actualAction
    from
    action
    :

    Code (CSharp):
    1. public InputActionReference action = null;
    2.     InputActionRebindingExtensions.RebindingOperation rebindOperation = null;
    3.  
    4.     InputAction actualAction;
    5.  
    6.     void Start()
    7.     {
    8.         foreach (var map in SettingsManager.Instance.control.actionMaps)
    9.         {
    10.             foreach (var tempAction in map.actions)
    11.             {
    12.                 if (tempAction.name == action.action.name)
    13.                 {
    14.                     actualAction = tempAction;
    15.                     break;
    16.                 }
    17.             }
    18.             if (actualAction != null)
    19.             {
    20.                 break;
    21.             }
    22.         }
    23.  
    24.     }
    This is the code that runs from the button component when I want to listen for a new keybind.

    Code (CSharp):
    1. public void Do()
    2.     {
    3.         if (actualAction == null) return;
    4.  
    5.         actualAction.Disable();
    6.  
    7.         rebindOperation = actualAction.PerformInteractiveRebinding(0)
    8.                     .WithControlsExcluding("<Pointer>/position") // Don't bind to mouse position
    9.                     .WithControlsExcluding("<Pointer>/delta") // To avoid accidental input from mouse motion
    10.                     .WithCancelingThrough("<Keyboard>/escape")
    11.                     .OnMatchWaitForAnother(0.1f)
    12.                     .OnComplete(operation => { OnCompletion(); })
    13.                     .Start();
    14.  
    15.     }
    OnCompletion() may be whatever you need for your case. Don't forget to dispose rebindOperation!
    Code (CSharp):
    1. void OnCompletion()
    2.     {
    3.         if (rebindOperation != null)
    4.             if (rebindOperation.completed)
    5.             {
    6.                 actualAction.Enable();// after this you can use the new key
    7.                 rebindOperation.Dispose();
    8.                 rebindOperation = null;
    9.                 Debug.Log("Remapped "+actualAction.name+" to "+ actualAction.bindings[0].effectivePath);
    10.  
    11.                 SettingsManager.Instance.StoreControlOverrides();
    12.             }
    13.  
    14.     }
    My input actions only need one binding, so I'm fine with
    actualAction.bindings[0]
    .

    When it comes to actually using the input, I don't use the default asset at all, but SettingsManager's.

    Code (CSharp):
    1. InputActionMap Game;
    2.  
    3.     void InitControls()
    4.     {
    5.         Game = SettingsManager.Instance.control.actionMaps[0];
    6.  
    7.         Game["Weapon1"].performed += ctx => UseWeapon(ctx, 0);
    8.         Game["Weapon2"].performed += ctx => UseWeapon(ctx, 1);
    9.         Game["Weapon3"].performed += ctx => UseWeapon(ctx, 2);
    10.         Game["Weapon4"].performed += ctx => UseWeapon(ctx, 3);
    11.         Game["Weapon5"].performed += ctx => UseWeapon(ctx, 4);
    12.         Game["Weapon6"].performed += ctx => UseWeapon(ctx, 5);
    13.  
    14.         //et cetera
    15.  
    16.     }
    In my case I'm writing
    Game["Weapon1"]
    rather than
    Controls.Game.Weapon1
    , what I would do if I were using the default C# wrapper. I only have one action map, so
    ...actionMaps[0]
    is enough for me.

    Hopefully I covered everything.
     
    trnenmic and pantang like this.
  43. AlterHaudegen

    AlterHaudegen

    Joined:
    Jul 8, 2013
    Posts:
    28
    @ZachariBarnes @pantang @Vagabond_

    A small update on this: I was finally able to get it to work (after repeatedly trying from scratch), but it only ever does work when using Player Input (I'm using Unity Events, haven't tried the other options on Player Input), not with custom instances of the generated C# classes. And it also *only* works when I'm creating a new Input asset (containing the player and UI schemes) from the Player Input script, *not* with a custom asset created through Asset -> Create -> Input Actions.

    I'm using the Sample Rebinding UI stuff, the only thing I had to change there was deactivating and reactivating the action when performing the interactive rebind, everything else just worked (again, when using Player Input over code *and* creating the Input Actions asset from the Player Input inspector).

    Saving the binding through playerInput.actions.SaveBindingOverridesAsJson also works without issue (1.1 p1/p2).
     
  44. Yukken

    Yukken

    Joined:
    Jul 12, 2015
    Posts:
    93
    My thread didn't get any replies but in my experience, the bindings are applied on a per asset basis. The generated C# classes create new runtime only SO assets so they never get any rebinding effects. It's interesting that you mention that it works for assets generated through player input.

    Since you've mentioned interactive rebinding, are you using the default rebind button prefabs? Those use input action references, I can't imagine anything being different even with assets created through player input with them. Unless you are calling the interactive rebind manually in code.
     
  45. josenajarqs

    josenajarqs

    Joined:
    Jan 27, 2021
    Posts:
    22
    Hi, I don't want to remap the same action with the same key, does anyone know a good way to do it? For example, that the same key for jumping is not for attacking
     
  46. AlterHaudegen

    AlterHaudegen

    Joined:
    Jul 8, 2013
    Posts:
    28
    That seems to be why rebinds are never applied when instantiating based on the generated classes, I agree. It also does not (for me) work like that even with assets created through PlayerInput.

    And yes, I have no idea how the assets manually created would be different from the ones created through PlayerInput. I'm just glad that I finally got something to work... whole thing is pretty messy. I'm using the prefabs from the samples, the only thing I had to modify was deactivating and reactivating the actions, no other code was changed by me.
     
  47. AlterHaudegen

    AlterHaudegen

    Joined:
    Jul 8, 2013
    Posts:
    28
    No idea at the moment, but I'm trying to solve it as well. If I manage to do that, I'll post back here (unless there is a thread dedicated to the topic).
     
  48. josenajarqs

    josenajarqs

    Joined:
    Jan 27, 2021
    Posts:
    22
    I posted something similar but did not receive any response, I am remapping the keys in my main menu, but I am not sure if there is a function to avoid that, if the key is the same, ignores it.
     
  49. AlterHaudegen

    AlterHaudegen

    Joined:
    Jul 8, 2013
    Posts:
    28
    @josenajarqs

    I changed the OnComplete of PerformInteractiveRebind from the sample to:


    Code (CSharp):
    1. .OnComplete(
    2.                     operation =>
    3.                     {
    4.                         m_RebindOverlay?.SetActive(false);
    5.                         m_RebindStopEvent?.Invoke(this, operation);
    6.                         action.Enable();
    7.  
    8.                         // Remove this binding if a duplicate is found.
    9.  
    10.                         if(CheckDuplicateBinding(action.bindings[bindingIndex])){
    11.                             Debug.Log("Duplicate binding found, restart interactive rebind");
    12.                             action.RemoveBindingOverride(bindingIndex);
    13.                             CleanUp();
    14.                             PerformInteractiveRebind(action, bindingIndex, true);
    15.                             return;
    16.                         };
    17.  
    18.                         playerInputPersistence.Save();
    19.                      
    20.                         UpdateBindingDisplay();
    21.                         CleanUp();
    22.  
    23.                         // If there's more composite parts we should bind, initiate a rebind
    24.                         // for the next part.
    25.                         if (allCompositeParts)
    26.                         {
    27.                             var nextBindingIndex = bindingIndex + 1;
    28.                             if (nextBindingIndex < action.bindings.Count && action.bindings[nextBindingIndex].isPartOfComposite)
    29.                                 PerformInteractiveRebind(action, nextBindingIndex, true);
    30.                         }
    31.                     });
    and used this method to check for duplicate bindings:


    Code (CSharp):
    1. private bool CheckDuplicateBinding(InputBinding bindingToCheckAgainst){
    2.  
    3.             foreach (var binding in playerInputPersistence.playerInput.actions.bindings)
    4.             {
    5.  
    6.                 // Don't test against itself, would always return true.
    7.                 if(binding == bindingToCheckAgainst)
    8.                 {
    9.                     continue;
    10.                 }
    11.  
    12.                 if(binding.effectivePath == bindingToCheckAgainst.effectivePath)
    13.                 {
    14.                     Debug.Log("Duplicate binding found: " + binding.effectivePath + ", " + bindingToCheckAgainst.effectivePath);
    15.                     return true;
    16.                 }
    17.             }
    18.  
    19.             return false;
    20.         }
    This does not cover all cases (you can for example still end up with duplicates after resets, but should get you started.
     
    pantang likes this.
  50. Roboserg

    Roboserg

    Joined:
    Jun 3, 2018
    Posts:
    83
    Do I understand it correctly that if I use the generated input action C# .cs class (and not PlayerInput or the asset directly) the rebindings done via "PerformInteractiveRebinding()" won't work?