Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Am getting multiple key events in new Input System, only one should be firing

Discussion in 'Scripting' started by seejayjames, Mar 9, 2021.

  1. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    692
    Am new to the new Input System so maybe am overlooking something simple, but I've created an action in the Input Action Asset, bound it to a key, and used the default "Button" with no Interactions (it says none are needed to use as a standard button). It calls a method that just prints "key pressed". I get 2 triggers when the key is pressed and 2 when released, it should only be 1 when pressed, and nothing when released. If I set the Interactions/Trigger Behaviors, same results, extra presses everywhere. Press Point settings make no difference. What's the deal?
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,931
    You're most likely getting multiple callbacks for all the different events in the button actuation sequence. How are you hooking up your listeners for the inpuit action?

    If you're using "Invoke UnityEvents", you will get at least 3 calls for every button press:
    1. Started phase
    2. Performed phase
    3. Cancelled phase
    https://docs.unity3d.com/Packages/c...UnityEngine.InputSystem.InputActionPhase.html

    You can disambiguate between them by reading the InputAction.CallbackContext object you get in your function. It has a phase property: https://docs.unity3d.com/Packages/c...InputSystem_InputAction_CallbackContext_phase

    Alternatively you can use C# events and control precisely which action phase you want a callback for.
     
  3. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    692
    The InputActionPhase sounds like it should work, but I don't know how to access it. Right now the function has no arguments, and if I put an InputActionPhase argument in, the function no longer shows up in the Inspector event chooser.
    The screenshot shows it selected, there's no arguments, and it works, but it's getting the multiple phases like you said. The code is just

    Code (CSharp):
    1. public void testKeyInput()
    2.     {
    3.         print("key P pressed");
    4.     }
    so, is there an easy addition to that so I can test which phase it's in? Does it need a dedicated listener? I thought just the method could be called, but I guess because there are multiple calls to it, I'd need a specific listener.

    I also would be fine with C# events, but would need to look that up. Wanted to see how it works with Unity Events first.

    screenshot_input_controls_event_keyboard_test.PNG
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,931
    You need to use a parameter of type InputAction.CallbackContext then reassign the function in the UnityEvent with the dynamic parameter.
    Code (CSharp):
    1. public void testKeyInput(InputAction.CallbackContext context)
    2.     {
    3.         print("key P pressed in phase " + context.phase.ToString());
    4.     }
     
  5. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    692
    Ah! Got it. I missed seeing the function in the Event function list at first because it's in the Dynamic section, not in the Static section where I'm used to looking for them. It was 3am so I blame that haha. Works great and I should be able to figure the rest out, the new system looks like a big improvement once things are set up. Thanks!

    Code (CSharp):
    1. public void testKeyInput(InputAction.CallbackContext context)
    2.     {
    3.         if (context.started == true) // "== true" is just for readability
    4.         {
    5.             print("key P pressed");
    6.         }
    7.         else if (context.canceled == true)
    8.         {
    9.             print("key P released");
    10.         }
    11.     }
     
    msclower likes this.