Search Unity

  1. Are you interested in providing feedback directly to Unity teams? Sign up to become a member of Unity Pulse, our new product feedback and research community.
    Dismiss Notice

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:
    187
    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

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,675
    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

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,675
    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:
    43
    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.
     
    Hello258 likes this.
  9. hipinds

    hipinds

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

    rboerdijk

    Joined:
    Aug 4, 2018
    Posts:
    93
    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
    bjornsyse and Zyphial like this.
  11. loganolson-dd

    loganolson-dd

    Joined:
    Sep 14, 2017
    Posts:
    4
    +1
     
    Hello258 likes this.
  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. loten

    loten

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

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    187
    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:
    20
    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:
    187
    josenajarqs likes this.
  18. josenajarqs

    josenajarqs

    Joined:
    Jan 27, 2021
    Posts:
    20
    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:
    20
    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:
    41
    =))))))))))

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

    bjornsyse

    Joined:
    Mar 28, 2017
    Posts:
    58
    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:
    187
    @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:
    58
    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:
    58
    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.


     
  25. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    187
    @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:
    49
    Just hit this issue as well. Hopefully there's a planned solution (or workaround).
     
  27. mattparisheveri

    mattparisheveri

    Joined:
    Oct 19, 2020
    Posts:
    2
    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:
    43
    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:
    1
  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:
    25
    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:
    187
    @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

    Unity Technologies

    Joined:
    Sep 15, 2012
    Posts:
    1,675
    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.
     
    zIyaGtVm and PaulNK like this.
unityunity