Search Unity

Using ButtonWithOneModifier without triggering another action using the same binding?

Discussion in 'Input System' started by Mman1235, Nov 9, 2019.

  1. Mman1235

    Mman1235

    Joined:
    Aug 23, 2015
    Posts:
    2
    Hi,

    Been using as of late the new package, and it is an absolute joy to use.

    I have only really encountered one issue (aside from maybe fleshing out the documentation farther).

    Let's say I have 2 actions:

    actionA uses a button with a press interaction.

    actionB uses a ButtonWithOneModifier the modifier is assigned to some stick direction,
    but the button is assigned to the same binding and interaction as actionA.

    Now whenever I trigger actionB, actionA triggers right after B.

    Now I have in my game's logic a way to bypass this,
    but I don't want to manage in the game code state's on if an action performed event should do it's logic or not.

    Is there a way using only the InputSystem to not cause actionA to perform right after actionB?

    Thanks!
     
  2. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    One way I have gotten around this issue is to define a custom composite like ButtonWithOneModifier, but with a bool that negates the modifier when set to true. With this setup, you can use that composite for both actions, so that one action can produce a non-zero value only when the modifier is pressed, and the other only when the modifier is not pressed. Here's a link for defining custom composites: https://docs.unity3d.com/Packages/c...14044167.1563642269#writing-custom-composites
     
  3. Mman1235

    Mman1235

    Joined:
    Aug 23, 2015
    Posts:
    2
    Thanks for the suggestion!

    Though i'm still contemplating if this would be the best course of action.
     
  4. nickleplated

    nickleplated

    Joined:
    Nov 2, 2018
    Posts:
    26
    What I ended up doing was to override the Keyboard layout and add a new inverted synthetic control that returns 1 if no modifiers are pressed and 0 if any of them are. Then I can just use the standard "Button with One Modifier".

    When I don't want a modifier pressed, I set the Modifier path to "<Keyboard>/noModifier".

    It's only set up to work with the keyboard modifiers, but it's good enough for me until an official solution comes out.

    Code (CSharp):
    1. #if UNITY_EDITOR
    2. using UnityEditor;
    3. #endif
    4. using UnityEngine;
    5. using UnityEngine.InputSystem;
    6. using UnityEngine.InputSystem.Controls;
    7. using UnityEngine.InputSystem.Layouts;
    8. using UnityEngine.InputSystem.LowLevel;
    9.  
    10. #if UNITY_EDITOR
    11. [InitializeOnLoad] // Make sure static constructor is called during startup.
    12. #endif
    13. [InputControlLayout(stateType = typeof(KeyboardState), isGenericTypeOfDevice = true)]
    14. [UnityEngine.Scripting.Preserve]
    15. public class KeyboardEx : Keyboard
    16. {
    17.     /// <summary>
    18.     /// A Button control that returns the opposite of the pressed state.
    19.     /// If the button is pressed, returns 0.0 and if not pressed, returns 1.0.
    20.     /// </remarks>
    21.     [UnityEngine.Scripting.Preserve]
    22.     public class InvertButtonControl : ButtonControl
    23.     {
    24.         ////TODO: wasPressedThisFrame and wasReleasedThisFrame
    25.  
    26.         public override unsafe float ReadUnprocessedValueFromState(void* statePtr)
    27.         {
    28.             return base.ReadUnprocessedValueFromState(statePtr) > 0f ? 0f : 1f;
    29.         }
    30.     }
    31.  
    32.     /// <summary>
    33.     /// An artificial inverted combination of <see cref="leftShiftKey"/>, <see cref="rightShiftKey"/>,
    34.     /// <see cref="leftCtrlKey"/>, <see cref="rightCtrlKey"/>,
    35.     /// <see cref="leftAltKey"/>, and <see cref="rightAltKey"/> into one control.
    36.     /// </summary>
    37.     /// <value>Control representing a combined left and right shift, control, and alt key.</value>
    38.     /// <remarks>
    39.     /// This is a <see cref="InputControl.synthetic"/> button which is considered pressed whenever the left and
    40.     /// right shift, control, and alt keys are not pressed.
    41.     /// </remarks>
    42.     public InvertButtonControl noModifier { get; private set; }
    43.  
    44.     protected override void FinishSetup()
    45.     {
    46.         base.FinishSetup();
    47.  
    48.         noModifier = GetChildControl<InvertButtonControl>("noModifier");
    49.     }
    50.  
    51.     static KeyboardEx()
    52.     {
    53.         const string json = @"
    54.    {
    55.        ""name"" : ""KeyboardEx"",
    56.        ""extend"" : ""Keyboard"",
    57.        ""controls"" : [
    58.            {
    59.                ""name"" : ""noModifier"",
    60.                ""layout"" : ""DiscreteButton"",
    61.                ""usage"" : ""Modifier"",
    62.                ""offset"" : 0,
    63.                ""bit"" : 51,
    64.                ""sizeInBits"" : 8,
    65.                ""synthetic"" : true
    66.            }
    67.        ]
    68.    }";
    69.  
    70.         InputSystem.RegisterLayoutOverride(json);
    71.     }
    72.  
    73.     // In the Player, trigger the calling of our static constructor
    74.     // by having an empty method annotated with RuntimeInitializeOnLoadMethod.
    75.     [RuntimeInitializeOnLoadMethod]
    76.     private static void Init()
    77.     {
    78.     }
    79. }
    80.  
     
    fstorehaug likes this.
  5. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Yeah, unfortunately ATM it's down to workarounds. We have this on the list as a high priority item. The fact that actions will indiscriminately consume input instead of figuring out priority among them is a source of problems in a couple areas. Unfortunately, the needed change here won't happen for 1.0 but I'm sure it'll be one of the first things that'll get picked up after.
     
    Hello258, bjornsyse and nickleplated like this.
  6. Ziboo

    Ziboo

    Joined:
    Aug 30, 2011
    Posts:
    356
    Any news on that issue ?
     
  7. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    Nothing in the way of implementation yet but it'll get worked on soon.
     
    Hello258 likes this.
  8. Why485

    Why485

    Joined:
    Jun 30, 2013
    Posts:
    45
    This has been an issue for me as well as my game has a lot of key combinations. For example F to do one action, and Shift+F to do the opposite action. I've temporarily worked around it with some messy input code to block input from one of the actions for a frame but this is quite ugly and not sustainable as the user needs to be able to create their own custom combination keybinds.

    Next time I'm working on input, I'll have a look through the workarounds posted here, but this is a very relevant issue for me.
     
    nehvaleem and Hello258 like this.
  9. hipinds

    hipinds

    Joined:
    Aug 31, 2017
    Posts:
    5
    Is this fixed? I'm facing this issue atm
     
  10. rboerdijk

    rboerdijk

    Joined:
    Aug 4, 2018
    Posts:
    96
    Same here

    Using Input System 1.1.0 preview 2, I did find an "InvertProcessor" and to test setup one Action with ShiftKey+DeltaMouse and the Other with (Inverted-ShiftKey)+DeltaMouse.
    Both actions however trigger when pressing shift, so the "Invert" seems to be ignored (probably it only works inverting binding-values, not for inverting input-modifiers).
    InvertProcessor.png

    I also could not get the "<Keyboard>/noModifier" example to work. Added the example script into a .cs file in my project, but the "noModifier" keyboard mapping does not appear.
     
    Last edited: Nov 9, 2020
    Pitou22, bjornsyse and Zyphial like this.
  11. loganolson-dd

    loganolson-dd

    Joined:
    Sep 14, 2017
    Posts:
    4
  12. Zyphial

    Zyphial

    Joined:
    Dec 27, 2020
    Posts:
    2
    Yeah, it appears to be ignored. That's a real bummer and hopefully easier to fix than a total overhaul. I have a hard time envisioning logic that can detect if a modifier is down but not if a modifier isn't down && this invert processor flag is set.
     
  13. ColdHand

    ColdHand

    Joined:
    Apr 10, 2018
    Posts:
    7
    I also have this problem as well. I'm making a fighter game, and while I have no problem with Keyboard scheme because it doesn't use any modifier, The gamepad scheme uses the modifier to differentiate the normal attack and special attack by pressing the Left shoulder and its respective button. So any progress on this problem?
     
  14. MinoanStudios

    MinoanStudios

    Joined:
    Dec 10, 2017
    Posts:
    11
    High priority over a year now... @Rene-Damm any news?
     
    kyleyoungblom and rboerdijk like this.
  15. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    Hello everybody! I have been working on a solution to this issue and I just got around to publishing my personal solution on github for everyone to use. You can set up combos with unlimited modifiers (each one being negatable). Here's the link: TRS6123/AginerianInput (github.com). Hope you all find this useful!
     
  16. josenajarqs

    josenajarqs

    Joined:
    Jan 27, 2021
    Posts:
    22
    Hi, Could you help me please? I know it has nothing to do with this, but do you know why this error happens?
     

    Attached Files:

  17. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    josenajarqs likes this.
  18. josenajarqs

    josenajarqs

    Joined:
    Jan 27, 2021
    Posts:
    22
    thanks for your answer! what I want is to remmap my keys from the menu (in another scene) the code works fine for me when I test it with my player (not prefab) in the "Gameplay" scene, but when I drag my player (the prefab from the "Gameplay" scene) to the menu code, I get this error: Cannot switch to actions "menu" input is not enable. I have this code in the Menu

    Code (CSharp):
    1. [SerializeField] private InputActionReference jumpAction = null;
    2.         [SerializeField] private PlayerController playerController = null;
    3.         [SerializeField] private TMP_Text bindingDisplayNameText = null;
    4.         [SerializeField] private GameObject startRebindObject = null;
    5.         [SerializeField] private GameObject waitingForInputObject = null;
    6.  
    7.         private InputActionRebindingExtensions.RebindingOperation rebindingOperation;
    8.  
    9.         private const string RebindsKey = "rebinds";
    10.  
    11.  
    12.         public void StartRebinding()
    13.         {
    14.             startRebindObject.SetActive(false);
    15.             waitingForInputObject.SetActive(true);
    16.  
    17.             playerController.PlayerInput.SwitchCurrentActionMap("Menu");
    18.  
    19.             rebindingOperation = jumpAction.action.PerformInteractiveRebinding()
    20.                 .WithControlsExcluding("Mouse")
    21.                 .OnMatchWaitForAnother(0.1f)
    22.                 .OnComplete(operation => RebindComplete())
    23.                 .Start();
    24.         }
    25.  
    26.         private void RebindComplete()
    27.         {
    28.             int bindingIndex = jumpAction.action.GetBindingIndexForControl(jumpAction.action.controls[0]);
    29.  
    30.             bindingDisplayNameText.text = InputControlPath.ToHumanReadableString(
    31.                 jumpAction.action.bindings[bindingIndex].effectivePath,
    32.                 InputControlPath.HumanReadableStringOptions.OmitDevice);
    33.  
    34.             rebindingOperation.Dispose();
    35.  
    36.             startRebindObject.SetActive(true);
    37.             waitingForInputObject.SetActive(false);
    38.  
    39.             playerController.PlayerInput.SwitchCurrentActionMap("Gameplay");
    40.         }
    41.     }
    42. }
    And this is in the PlayerController
    Code (CSharp):
    1.   [SerializeField] private PlayerInput playerInput = null;
    2.         [SerializeField] private CharacterController controller = null;
    3.  
     
  19. josenajarqs

    josenajarqs

    Joined:
    Jan 27, 2021
    Posts:
    22
    everything works fine, i use the same menu script in the scene where the game starts and drag my ObjectPlayer to the script, remap my keys and everything works fine, but in the menu scene when trying to drag my PlayerPrefab to the script and try remapping the keys the same error appears, Cannot Switch action "menu" is not enabled
     
  20. Boji

    Boji

    Joined:
    Jul 10, 2012
    Posts:
    44
    =))))))))))

    Maybe you need one more year to work on it...
     
    Itschotsch likes this.
  21. bjornsyse

    bjornsyse

    Joined:
    Mar 28, 2017
    Posts:
    102
    Fantastic, thank you for your effort!

    Hi, would this work with Keyboard composites as well? Like Up/Down-arrow composite + a negated modifier key?
     
  22. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    @bjornsyse Thanks for your appreciation! As for your question, if you duplicate the axis binding, set one binding to the Up Arrow, and set the other binding to the Down Arrow with the Invert Processor, you should get the desired result.
     
  23. bjornsyse

    bjornsyse

    Joined:
    Mar 28, 2017
    Posts:
    102
    Hi

    Hmm, I never thought about like that. I though we had to engage the positive/negative variables and do the calculation like in the other composites (AxisComposite) for example. Have you tried your suggestion? I couldn't get it to work over here. Might be missing something.

     
  24. bjornsyse

    bjornsyse

    Joined:
    Mar 28, 2017
    Posts:
    102
    Hi again. In the meantime, I ended up using the script provided by @_s_e_r_ in this thread (
    AxisModifierComposite 
    ) but modified it by adding this boolean flag to check for an Inverted state of the modifier key. That is, whether the state of the modifier key NOT being pressed should gate the action in question.

    Code (CSharp):
    1. public bool invertModifier;
    2.    
    3.     // This method computes the resulting input value of the composite based
    4.     // on the input from its part bindings but gated by the modifier key.
    5.     public override float ReadValue(ref InputBindingCompositeContext context)
    6.     {
    7.         float baseValue = base.ReadValue(ref context);
    8.        
    9.         if (!invertModifier)
    10.         {
    11.             if (context.ReadValueAsButton(modifier))
    12.                 return base.ReadValue(ref context);
    13.             return default;
    14.         }
    15.  
    16.         if (!context.ReadValueAsButton(modifier))
    17.             return base.ReadValue(ref context);
    18.         return default;
    19.     }
    20.    
    Works well for me.


     
    ArosRex likes this.
  25. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    @bjornsyse Admittedly I didn't try my suggestion until today and I see that the inverted axis binding won't work as expected. I just submitted changes to the git repo to fix the issue. It now works well on my end.
     
    bjornsyse likes this.
  26. Saucyminator

    Saucyminator

    Joined:
    Nov 23, 2015
    Posts:
    61
    Just hit this issue as well. Hopefully there's a planned solution (or workaround).
     
  27. mattstromaneveri

    mattstromaneveri

    Joined:
    Oct 19, 2020
    Posts:
    4
    Rene-Damm , what's the status here please? This is a big issue for us as an ISS customer.
     
  28. Why485

    Why485

    Joined:
    Jun 30, 2013
    Posts:
    45
    I haven't tried this recently, so I don't know if this has been fixed or not yet, but this issue was a deal breaker for me a almost exactly a year ago and caused me to switch back to the old input system and Rewired for an input solution.
     
  29. zjkipping

    zjkipping

    Joined:
    Jun 10, 2018
    Posts:
    1
    @Rene-Damm Is there any status update with this? This is pretty large break if you want your users to set their own arbitrary custom key binds... Or just having modifiers on such any action. Such as Q (Drop one item), Shift-Q (drop item stack), Ctrl-Q (drop half item stack) … Currently we could work around this knowing the main action and only allowing to change the modifier & action independently. Though this is really FAR from ideal, especially since it breaks if the user just wantonly assigns a random button to 1 & another to Shift-1...
     
  30. probbins

    probbins

    Joined:
    Oct 19, 2010
    Posts:
    216
    Just ran into this issue as well, would be great to get it resolved. @Rene-Damm
     
  31. marcinpiotrowski

    marcinpiotrowski

    Joined:
    Jan 10, 2021
    Posts:
    3
  32. jay_unity564

    jay_unity564

    Joined:
    Dec 3, 2020
    Posts:
    1
    It's been over 16 months since there's been any word on this from Unity. Can we get an update.
    Input system is kind of a joke with such a fundamental flaw.
     
  33. NeonTheCoder

    NeonTheCoder

    Joined:
    Feb 1, 2014
    Posts:
    40
    This is a huge issue imo. There's no point to a button with modifier if it triggers the underlying non modifier actions.
    I tried to use trs6123's git solution but it didn't seem to show up in my ui.
    The invert component makes sense to use on the modifier to set it to always on that way you can set other actions to not trigger on a modifier press.
    Can't believe something so simple that needs to be fixed has been ignored for over a year when its considered a "high priority issue"
     
  34. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
    @NeonTheCoder I just updated my repo to fix the issue with custom modifiers not showing up in UI after entering playmode. Turns out calling InputSystem.RegisterXXX more than once for the same type unregisters it, which is very likely a bug on Unity's side.
     
  35. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    There's a working first implementation. Needs some more work and there's also some surrounding issues that need solving (like ensuring that for shortcuts specifically, the order of keypresses is respected). But looking promising. We do consider this one of the higher-priority missing things.
     
  36. MarkusKreutz

    MarkusKreutz

    Joined:
    Jul 22, 2021
    Posts:
    1
    @Rene-Damm So how exactly does this solution work? Which Unity version will I need, and which version of the new InputSystem?
     
  37. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    <ah doh... mixed up my tabs in the initial post and posted the wrong thing here>

    While the managed changes have landed, the native changes haven't made it out yet. They're making their way through the merge queues but takes a bit to hit the various release trains. I'll post here when the native changes have made it.
     
    jmcusack likes this.
  38. nehvaleem

    nehvaleem

    Joined:
    Dec 13, 2012
    Posts:
    436
    wow, didn't expect such issue to be present in a system that have been here for a while. Also stumbled upon the situation when action with modifier is being called alongside with action without one (if they use the same button). I would really appreciate some... input on it :D
     
  39. bjornsyse

    bjornsyse

    Joined:
    Mar 28, 2017
    Posts:
    102
    Any news on this end, or are we still waiting for a solution? I'm on 1.1.1 and as far as the package manager will show my that's the latest yes?

    However documentation shows a 1.2 version (https://docs.unity3d.com/Packages/com.unity.inputsystem@1.2/manual/index.html) . How do I get that one? (i'm on Untiy 2021 branch), and does that version have any updates to remedy this issue?

    upload_2021-12-3_9-29-23.png
     
  40. deathsride18

    deathsride18

    Joined:
    Jun 9, 2020
    Posts:
    4
    I find it strange it was released in this state at all. The modifiers are essentially useless due to this and should not currently be in the package.
     
  41. deathsride18

    deathsride18

    Joined:
    Jun 9, 2020
    Posts:
    4
    If you are looking at this in the future. Create a script in your editor folder and look through nickleplated's solution. This works only for PC but it works wonderfully. Thanks @nickleplated
     
  42. Omi

    Omi

    Joined:
    Dec 2, 2012
    Posts:
    9
    I'm currently wrestling with this issue and am curious about how a fix is progressing. Any update?
     
  43. nehvaleem

    nehvaleem

    Joined:
    Dec 13, 2012
    Posts:
    436
    @Rene-Damm could you please update us a bit? Please read the comments in this thread, this is a bit absurd for such things to take this much time without clear communication.

    I think we would really appreciate some info about the resolution or suggested (working) workarounds.
     
  44. lightningGamer

    lightningGamer

    Joined:
    Feb 19, 2013
    Posts:
    52
    Does anyone know if there is an update on this or if the 1.3 version of the input system has fixed this problem?
     
  45. IterativeKing

    IterativeKing

    Joined:
    Apr 17, 2019
    Posts:
    5
    Still a known limitation in the docs for 1.3
     
  46. FYI: they almost got it working in October, but then for some reason backed out:
    https://github.com/Unity-Technologies/InputSystem/pull/1405
     
  47. nicbarkeragain

    nicbarkeragain

    Joined:
    Oct 12, 2019
    Posts:
    5
    > I find it strange it was released in this state at all. The modifiers are essentially useless due to this and should not currently be in the package.

    Have to agree with this one, it's such a strange design decision to even support modifiers at all if they can't be distinguished from the non modified key.

    Why would someone create a modified keybinding if the original key was unbound? It's just needless extra work for the player.
     
  48. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    246
  49. Konaju-Games

    Konaju-Games

    Joined:
    Jul 11, 2012
    Posts:
    22
    A two year old thread, a reportedly "high priority" issue, still not resolved, and now being ghosted by the dev team.

    @Rene-Damm it has been three months since pull 1405 was moved back to WIP, and it has not been touched since. What is the status of the native code changes that were apparently working their way through the system. Please don't let this be yet another forum thread that is left to die without resolution.
     
    yakivmospan likes this.
  50. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    This one is not blocked on native code changes. PR 1405 was just about to land when we discovered a number of issues with it that we overlooked initially.

    It's not landing in 1.4 but it's alive. There is some exciting stuff brewing and this one is going in.
     
    Lurking-Ninja likes this.