Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only.

    Please, do not make any changes to your username or email addresses at id.unity.com during this transition time.

    It's still possible to reply to existing private message conversations during the migration, but any new replies you post will be missing after the main migration is complete. We'll do our best to migrate these messages in a follow-up step.

    On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live.


    Read our full announcement for more information and let us know if you have any questions.

Question PerformInteractiveRebinding not working

Discussion in 'Input System' started by lam000, May 15, 2020.

  1. lam000

    lam000

    Joined:
    Feb 21, 2019
    Posts:
    2
    Hello,

    I have an InputAction File with my Keybindings.
    Then I have a InputActionReference binded to an Action I want to override.

    When I click the button I want to be able to perform an InteractiveRebinding but it is not working

    Code (CSharp):
    1.  public void StartInteractiveRebind()
    2.     {
    3.         var rebindOperation = m_Action.action.PerformInteractiveRebinding()
    4.             // To avoid accidental input from mouse motion
    5.             .WithControlsExcluding("Mouse")
    6.             .WithCancelingThrough("<Keyboard>/escape")
    7.             .OnMatchWaitForAnother(0.2f)
    8.             .Start();
    9.  
    10.     Debug.Log("finished");
    11.  
    12.     }
    but the Log message is beeing sent at the same time when I press the button so the Performinteractive is over before I even can enter a new key for the action

    Regards
     
    hassanali4 likes this.
  2. Voidsay

    Voidsay

    Joined:
    Jun 20, 2020
    Posts:
    6
    First of all I am sooo happy I've stumbled on your post. I have been trying to understand the provided examples for days now and your not quite working code was exactly what I needed. I managed to do everything I needed in minutes!

    To show my gratitude I would like to offer you some shaky explanation written by a guy with one year of c# experience.
    Anyway you have probably figured it out yourself by now, but perhaps others are interested. Anyway here it goes:

    First problem with your code (and probably the origin for your debug needs) you don't deactivate your action while rebinding it. An action cannot be rebound while it is in use, since it would cause uncertainty.

    It probably threw you a similar error to this:

    InvalidOperationException: Cannot rebind action 'Player/Jump[/Keyboard/space]' while it is enabled
    UnityEngine.InputSystem.InputActionRebindingExtensions+RebindingOperation.WithAction (UnityEngine.InputSystem.InputAction action) (at wherever your class is)


    Solution is easy, just disable it before the rebinding with:
    m_Action.action.Disable();


    and re enable it with:
    m_Action.action.Enable();


    Edit:
    You can detect when the rebinding is complete with:
     if(rebindOperation.completed)


    Now the second question. Why dose your Debug.Log() trigger before completion. I don't have a nice answer, but in my limited understanding it boils down to the following:
    The command isn't really a step like
    int i=1+1;
    but more like a MonoBehaviour similar to
    Invoke(someFunction, someTimeLater);
    that triggers every once in a while and checks for inputs that satisfy the parameters.
    Basically you mistake the rebind being complete when in fact it is still running (or already legitimately completed).

    Since I have a similar base code to you I would like to use this chance to post a working script, that might use some optimization regarding the reactivation of the action. (btw. dose that "m_" before Action mean something? cause I just use Action as a public variable)

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. public class RebindScript : MonoBehaviour
    5. {
    6.     public InputActionReference Action;
    7.     private InputActionRebindingExtensions.RebindingOperation rebindOperation; // this should be "optimised", since doing updates every frame is inefficient
    8.  
    9.     void Update()
    10.     {
    11.         if (rebindOperation != null)
    12.             if (rebindOperation.completed)
    13.             {
    14.                 Action.action.Enable();// after this you can use the new key
    15.                 Debug.Log("finished");
    16.             }
    17.     }
    18.  
    19.     public void StartInteractiveRebind()
    20.     {
    21.         Action.action.Disable(); // critical before rebind!!!
    22.         rebindOperation = Action.action.PerformInteractiveRebinding()
    23.             .WithControlsExcluding("Mouse")
    24.             .WithCancelingThrough("<Keyboard>/escape")
    25.             .OnMatchWaitForAnother(0.2f)
    26.             .Start();
    27.     }
    28.  
    29. }
    Before I forget this script apparently eats alternative action bindings, so beware! If you have jump on 'space' and 'w' for example after this procedure you will only keep your new binding and will have to reload to have both back!

    I would like to apologize if the formatting is weird I am new to forums in general.


    Cordially the all consuming void.
     
    valentin56610, IggyZuk and hassanali4 like this.
  3. lam000

    lam000

    Joined:
    Feb 21, 2019
    Posts:
    2
    Thank you for the answer, I cant verify if you solution would have helped, because I have solved it myself by then.
    but for documentation my error was that PerformInteractiveRebinding needed an Bindingindex

    so changing my code to

    Code (CSharp):
    1.  public void StartInteractiveRebind()
    2.     {
    3.      
    4.  var m_RebindOperation = actionref.action.PerformInteractiveRebinding(1)
    5.             // To avoid accidental input from mouse motion
    6.             .WithControlsExcluding("Mouse")
    7.             .WithCancelingThrough("<Keyboard>/escape")
    8.             .OnMatchWaitForAnother(0.2f)
    9.             .Start().OnCancel(op =>
    10.             {
    11.                 CleanUp();
    12.                 Debug.Log("cancel");
    13.                 RebindOverlay.SetActive(false);
    14.                 KeybindMenu.SetActive(true);
    15.  
    16.             }).OnComplete(op =>
    17.             {
    18.                 SetPref(prefs, op.action.GetBindingDisplayString(1));
    19.                 textmesh.text = op.action.GetBindingDisplayString(1).ToUpper();
    20.                 StoreControlOverrides();
    21.                 Debug.Log("saved1");
    22.                 RebindOverlay.SetActive(false);
    23.                 KeybindMenu.SetActive(true);
    24.                 CleanUp();
    25.             });
    26.  
    27.         RebindOverlay.SetActive(true);
    28.         KeybindMenu.SetActive(false);
    29.     Debug.Log("finished");
    30.     }
    worked for me , keep in mind I also added an rebind overlay so that the user knows that he is rebinding
     
    hassanali4 likes this.
  4. Voidsay

    Voidsay

    Joined:
    Jun 20, 2020
    Posts:
    6
    I have noticed that the addition of the binding index resolves the issue I mentioned in the end of my reply. So putting one there is definitely recommended. Good to know!

    Also is there a reason you set Index 1 and not index 0 ? If you have only one binding preset that would cause an error (binding index out of range for action). If you have two preset it wouldn't cause an issue, but doing that would leave an "original" binding. Probably reading too much into this...

    Anyway your solution now looks a lot more like the recommended one in the example files. That must mean it's good.

    Good luck with your project!
    Cordially the talkative void
     
    hassanali4 likes this.