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. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

button trigger behaviour: "release only" triggers twice!?

Discussion in 'Input System' started by FeastSC2, Jul 8, 2019.

  1. Natzely

    Natzely

    Joined:
    Sep 9, 2017
    Posts:
    3
    Debug pictures of a Release Only event. The value zeros at when it's performed which is when the release event happens. So you would have to read the event at started event and use it during the performed event if you want the action to trigger when the user releases the button instead of when they press it.
     

    Attached Files:

  2. KwahuNashoba

    KwahuNashoba

    Joined:
    Mar 30, 2015
    Posts:
    110
    Let me join the party, this might be useful to someone :)

    I've also had this kind of issue, but with value-typed action. When I hit key on keyboard for brief period it triggers single time but if I hold it a bit longer, it triggers twice. What worked for me was to set Action Type to Pass Through but on Action itself, not the underlying bindings/composites. I left all the Interactions blank.

    Then I check for the input like this:

    Code (CSharp):
    1. public void OnMove(InputAction.CallbackContext context)
    2. {
    3.     if (context.action.phase == InputActionPhase.Performed)
    4.     {
    5.         ProcessMoveInput(context.action.ReadValue<Vector2>());
    6.     }
    7. }
     
  3. DemTsag

    DemTsag

    Joined:
    Nov 21, 2017
    Posts:
    1

    This worked for me. I have been trying to make this work 3 days now. Thank you so much!
     
  4. latrodektus

    latrodektus

    Joined:
    Nov 1, 2016
    Posts:
    13
    I've done this and it's working, switching off Started and Canceled events should be an option in the Input System Package settings in the Project Settings.
     
  5. Fressbrett

    Fressbrett

    Joined:
    Apr 11, 2018
    Posts:
    79
    Same problem still persisting in 2021.1.20f1.

    I just want to know when a button is pressed and when its being released within my handler function, not that hard of a task but its incredibly combersome to setup and tough to debug. If it wasn't for this thread, no way I would have found out why my events get fired twice, with the exact same action phase and triggered/started/performed values.

    If this is intended behaviour, its not at all well documented. It seems like when spawning PlayerInput prefabs through the PlayerInputManager, the Inputs get fired twice, once in the prefab instance, and once in the prefab - hence the valid scene check working, or alternatively you can check if the gameobject is acitve in the hierarchy (in case it will be always active this check seems like a bit less overhead, no idea what the performance of the valid scene check is):

    Code (CSharp):
    1.         public void HandleMyInput(CallbackContext context)
    2.         {
    3.             if (!IsInputAllowed) return;
    4.             // do your thing here
    5.         }
    6.  
    7.         private bool IsInputAllowed
    8.         {
    9.             get
    10.             {
    11.                 if (!gameObject.activeInHierarchy)
    12.                     return false;
    13.                 return true;
    14.             }
    15.         }

    For reference, this problem was discussed on stackoverflow too.
     
    Last edited: Dec 17, 2021
  6. LDMONTY007

    LDMONTY007

    Joined:
    Sep 7, 2019
    Posts:
    2
    Ok, if you read the unity manual on the input system it says if you just want to check if the button has been pressed only when it has been pressed (as in it won't continuously repeat like inputActionPhase.started does) all you have to do is use InputAction.Triggered. This gives you a boolean value, if the action (say a button) has been pressed it will output true, when it is released it switches back to false, this way it doesn't constantly trigger like InputAction.started it only triggers once when the button is pressed.
    Code (CSharp):
    1. if (InputAction.triggered)
    2.             {
    3.                 print("TRIGGERED");
    4.             }
     
  7. BillShackleton

    BillShackleton

    Joined:
    Mar 18, 2020
    Posts:
    1
    Thank You!
     
    Michal_Stangel likes this.
  8. ShokWayve

    ShokWayve

    Joined:
    Jan 16, 2013
    Posts:
    87
    I have also found a solution. Use the context to check the control.ispressed() function as below:

    Code (CSharp):
    1. if(context.control.IsPressed() == true)
    2.         {
    3.             Debug.Log("Left Button Clicked Baby!!");
    4.             return;
    5.         }
    I hope this helps someone.
     
  9. abitowhit

    abitowhit

    Joined:
    Aug 9, 2020
    Posts:
    13
    I was able to fix using a boolean if it helps anyone.
    I have a "Challenge Help" canvas (book) with fwd/bkwd TMP buttons which would fire a fwd and bkwd script to change text and an image.
    My problem was that onClick would fire and advance to the next page then the release would advance yet one more page (i.e. p1 to p3).

    I created a local bool in the script called allowPress in the script and a public void AllowPress which toggled allowPress to true.
    On the button "onClick" I first call AllowPress followed by the actual fwd/bkwd methods.
    onclickfix.png

    In both the fwd and bkwd methods I then added an initial check of the local allowPress being true and immediately set it to false. The second onRelease does not fire now because local allowPress is now false.

    e.g.
    Code (CSharp):
    1. public void forward()
    2. {
    3.     if(allowPress)
    4.     {
    5.         allowPress=false;
    6.         if(currentPage < pageText.Length-1)
    7.         {
    8.             currentPage++;
    9.          }
    10.         else{
    11.             currentPage=0;
    12.         }
    13.         updatePage();
    14.     }
    15. }
     
  10. davidnibi

    davidnibi

    Joined:
    Dec 19, 2012
    Posts:
    421
    I got this working by setting the interact button (the one that usually is on off on off etc) to Press and Release in Interactions, and used this:

    Code (CSharp):
    1.     public void OnInteract(InputAction.CallbackContext context)
    2.     {
    3.         if (context.canceled)
    4.         {
    5.             interactPressed = false;
    6.         }
    7.         else
    8.         {
    9.             interactPressed = context.action.triggered;
    10.         }
    11.     }
    It works 100% for me.
     
  11. Hypertectonic

    Hypertectonic

    Joined:
    Dec 16, 2016
    Posts:
    72
    I discovered that even if trying to check for phase, the reason it still fired twice for me appears to be because I had two InputMaps with the exact same action name and binding, and PlayerInput.cs just throws you the event twice, once for each InputMap.

    Since I did want both input maps to be on, and was still using SendMessages instead of UnityEvents, I managed to prevent the double execution like this:
    Code (CSharp):
    1. public void OnYourAction(InputValue value)
    2. {
    3.     if (PlayerInput.actions.FindAction("YourAction").inProgress) return;
    4.  
    5.     // code here only executes once
    6. }
     
    Last edited: Aug 27, 2022
  12. paulc218

    paulc218

    Joined:
    Jul 21, 2019
    Posts:
    5
    Hey everyone. I'm not sure if this problem being described here has been fixed, I just was stuck on a similar issue but was able to fix it and in doing so understand how and why my trigger buttons were firing 2-4 times on press and then one more time on release. I was using an xbox controller and it was only doing it for the triggers, bumpers were fine using InputActionName.performed but the triggers were firing multiple times.

    If I used InputActionName.canceled instead it fires only once, like a "on Button Up", and InputActionName.started also fired only once as a "on button down" effect, so if you have this repeated firing happening to you unintentionally, to get only one action taken on the button I suggest using one of those 2 options and not performed. Performed will fire constantly, until it reaches maximum button down, and then one more time on release. I believe this is the intended effect for controller trigger buttons, like a machine gun shooting kind of thing,

    But basically the variation in people's reports of how many times it is firing instead of once, is in my opinion how fast they are clicking the button and if you hold a trigger button half way pressed you will see the performed event firing constantly. So that explains the triggers, and my thinking about the problem happening on other buttons (mine were all set to the defaults) is that your action might be acting like my xbox trigger buttons were today. I wish I knew how to explain that part better, "I think" that is a press interaction you would need to adjust but I haven't touched those (yet).

    If you still find trouble with this and need to code around it, you would set a bool to true on the started/performed method and only run that method when that is set to false (if (!flag) return;) and then in your canceled method, set that flag to true again. That would insure a 1 to 1 ratio of performed to canceled calls at least and ignore rapid fire.
     
  13. brian-nielsen

    brian-nielsen

    Joined:
    Apr 18, 2018
    Posts:
    15
    I suppose I'll throw in my workaround as well. Using SendMessages() my OnClick method is firing four times. Below fires when the button is released.

    My "solution"

    Code (CSharp):
    1.     public void OnClick(InputValue value)
    2.     {
    3.         //Value wrapper for New Input System. This will fire 4 times on a single click without this wrapper.        
    4.         Debug.Log("On click input value = " + value.Get<float>());
    5.         if (value.Get<float>() >= 0f && value.Get<float>() < 1f)
    6.         {
    7.             //do stuff
    8.         }
     
  14. Malorke

    Malorke

    Joined:
    May 28, 2019
    Posts:
    1
    So I just had the issue and it appears that for my PS4 controller there is two set of input events, one for the controller DualShock4GamepadHID then another one for XInputControllerWindows.

    That explain why even with an if (context.performed) it still runs two times in one frame.

    I don't know how to solve that yet.
     
  15. KnightWhoSaysNi

    KnightWhoSaysNi

    Joined:
    Jan 21, 2017
    Posts:
    10
    Using Unity 2022.2.01f and Quest 2 Activate action (triggerPressed)
    action.performed was firing just once for a while. Then it started firing twice. Then it went back to firing once for no reason at all.

    I debugged the code and saw that it was firing twice. Restarted Unity and my PC twice. The problem persisted for a while and I didn't even bother fixing it as I was working on some other areas.

    Then a day later, and after the last debugging in Visual Studio the event started firing just once. -.-
    I didn't do anything. The problem fixed itself...for now.

    [Update]
    It started happening again and this time the action.performed wasn't firing just twice but it starts off with 2 event calls, and then every time I stop and play again it increases the number of calls.

    The only thing that seems to fix this is disabling "Enter Play Mode Options" in Project Settings/Editor. Initially I had this turned on and had no problems, then the event started firing twice. Then it stopped firing twice for a short while. And now it fires 5 or 6 or more times with every button press.

    Since it is painful to work in Unity without EnterPlayModeOptions turned on, for now I'll have to just manually check for the extra event calls.

    [Second Update]
    On action.performed I was doing something with a game object in the scene. If disable Enter Play Mode Options that game object's reference gets lost somehow. In Awake of the script that has the action the reference is alive, but when I press the button the reference is missing.

    No idea what the hell is going on. Unity just randomly started acting out it seems (everything was working fine for a while, initially).

    [Final Update] :D
    I wasn't unsubscribing from the event + EnterPlayModeOptions = multiple calls to the event handler. So, no bugs, totally my fault. The only thing that still makes no sense is why it worked correctly initially.
     
    Last edited: Dec 29, 2022
  16. jawsome290

    jawsome290

    Joined:
    Jan 20, 2023
    Posts:
    3
    FIX: Setup your action like this
    upload_2023-2-9_18-56-24.png
    Then, within the function where your action is called add an if statement to check if Control == 1
    1==Fully pressed
    0==Not Pressed
    Like this
    upload_2023-2-9_18-58-50.png
     
  17. bagelbaker

    bagelbaker

    Joined:
    Jun 5, 2017
    Posts:
    65
    We have the same issue, the ps4 gamepad acts as 2 separate devices that provides input. The extra XInputControllerWindows doesn't appear with a ps5 (dualsense) gamepad. And only once device (XInputControllerWindows) when using an xbox gamepad. This bug occurs on Unity 2022.2.6f1 and input system 1.3.0 through 1.5.0. The bug is not there on Unity 2021.3.4f1 with input system 1.3.0 through 1.5.0.

    I created a bug report: IN-32056
     
  18. DecayedBomb

    DecayedBomb

    Joined:
    Feb 7, 2013
    Posts:
    1
    Set the Player Input Behavior to "Send Messages"
    Name function in your code "On+("ActionName")"
    Example: Action name Jump, name your function OnJump();
    and everything will work how it should, no extra linking required.