Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Rebinding with optional Modifier keys

Discussion in 'Input System' started by tbryarly, Jun 4, 2020.

  1. tbryarly

    tbryarly

    Joined:
    Nov 22, 2016
    Posts:
    11
    I have been implementing the new Input System in my current game and am a bit flummoxed by rebinding.

    It appears that if a binding is setup as one type (Button, ButtonWithOneModifier, ButtonWithTwoModifiers) there's no way to rebind to a different type. (It looks like I could override the existing functionality and delete the old binding and create a new binding from code, but that's not a rebinding, and ignores the function calls clearly intended for rebinding.) Is there an intended way to do this that I am missing, or does this functionality not exist?

    As an example if it's not clear: I have an Action called Interact and bind it by default to the keyboard value 'E'. Then I have an options menu in my game where actions can be rebound. However I can not find any way (at least using PerformInteractiveRebinding()) to allow the user to rebind the Interact action to 'Shift-E' if they wanted to for some reason. I thought perhaps I could make all bindings ButtonWithTwoModifiers and leave the modifiers empty if needed, but that doesn't seem to work either.
     
  2. vecima

    vecima

    Joined:
    Jun 6, 2017
    Posts:
    16
    Can you create 2 or 3 bindings in the aciton and set it up such that only one of them is bound with a value? I haven't actually tried this, it's just an idea. You could have one Button binding and one ButtonWIthOneModifier and one ButtonWithTwoModifiers within the same action. It might be pretty complicated to figure out how the user wants to bind ... maybe if the binding process listens for all keys pressed and then finishes when no keys are pressed? and then keeps only the last 3 pressed at most.
     
  3. Rene-Damm

    Rene-Damm

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    The current rebinding support does indeed not yet have a whole lot of flexibility (well, you could argue it has none :)) in terms of *altering* the binding setup. In other words, except for being able to add new bindings (WithRebindingAddingNewBinding), there's no built-in support for having it automatically deal with bindings involving more than a single control. It's on the list.

    ATM the options are to either deal with this at the UI level or to manually script the respective logic by using the callbacks of RebindingOperation and synthetizing a composite binding from the list of candidate controls.
     
  4. tbryarly

    tbryarly

    Joined:
    Nov 22, 2016
    Posts:
    11
    Thanks for clearing that up. I was starting to pull my hair out thinking I was making things entirely too complicated. :p

    I might try multiple bindings and see if that's an easier approach but it's good to know I'm not spending time redoing functionality that already exists.
     
  5. JustLoren

    JustLoren

    Joined:
    Nov 12, 2017
    Posts:
    5
    Here we are, May of 2022.

    I'm trying to get over this hurdle at the moment. Any guidance?
     
  6. JustLoren

    JustLoren

    Joined:
    Nov 12, 2017
    Posts:
    5
    Specifically, the 1.3 changelog notes say this should work with buttons via this line:
    • If an binding of higher complexity "consumes" a given input, all bindings waiting to consume the same input will automatically get skipped. So, if a "Shift+B" binding composite consumes a "B" key press, a binding to "B" that is waiting in line will get skipped and not see the key press.
    Here's my binding:
    upload_2022-5-14_10-59-41.png

    I'm getting actions firing for both Interact and Secondary Interact, unfortunately.

    Is it relating to how I wrote my binding code?
    Code (CSharp):
    1. input = GetComponent<PlayerInput>();
    2. input.actions["Interact"].started += PrimaryStart;
    3. input.actions["Interact"].canceled += PrimaryEnd;
    4. input.actions["Secondary Interact"].started += SecondaryStart;
    5. input.actions["Secondary Interact"].canceled += SecondaryEnd;
     
  7. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    10,005
  8. Dehaku

    Dehaku

    Joined:
    Mar 8, 2021
    Posts:
    5
    What's the status on this? Not sure where to look. Can binding types be changed easily now in 1.4.4?
     
  9. tbryarly

    tbryarly

    Joined:
    Nov 22, 2016
    Posts:
    11
    I've been looking into this again and found a couple bits that can help:
    • Project Settings / Input System Package / Enable Input Consumption allows you to have two non-competing inputs (for instance, tab and shift-tab).
    • <InputAction>.PerformInteractiveRebinding(index).OnMatchWaitForAnother(1f) allows you to wait for the player to press multiple keys when rebinding.
    However, if you have a Binding (that does not have a modifier) and want to override it with a Binding that has a modifier, I do not see a direct way to do that with the current system. I also could get not a Binding with a modifier, where the modifier is set to none, to work. (So for instance you could bind to None-Tab and allow the player to rebind as Shift-Tab.)

    This leaves adding your own binding using the RebindingOperation callback as mentioned above, but that means that you have to externally keep track of what you have added as being an override and manage any changes. This seems like a giant pita to me, and looks like a pretty substantial shortcoming in the existing system.
     
  10. rdjadu

    rdjadu

    Joined:
    May 9, 2022
    Posts:
    103
    This should be doable by customizing
    OneModifierComposite
    that comes out of the box. Like, even copypasting it from GitHub, making sure
    modifier
    initializes to something like -1, and then modifying the read functions to just ignore the modifier when the field value is -1, should do the trick. I think :)

    But yeah, rebinding composites is... messy business.