Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question New input system triggering phases twice because of VALUE not key presses

Discussion in 'Input System' started by djweaver, Sep 16, 2020.

  1. djweaver

    djweaver

    Joined:
    Jul 4, 2020
    Posts:
    105
    So I've been struggling with a bug in my code where my context.start and context.performed were firing off an animation trigger twice when I realized that the way the new input system works when passing values through, is that any time you return to zero as a result of pressing two keys at once on say, a Vector2 configured for WASD movement for example, you will get TWO start or performed calls.

    Lets say you are pressing W (up) and your Vector2 reads (0, 1, 0). You get a call to start on this press.

    But lets say while still holding W, you press the S (down) key, which cancels out your movement entirely, bringing you back to (0, 0, 0). Now if you release S, while still holding W, you will get another start call because it has returned to (0,1,0), even though you never pressed another key... you just released one. Performed behaves the same way.

    Now color me stupid, but once I realized this I figured "well thats no biggie I can just use context.control.displayName to check for the KEY press", not the phase (or value)

    but lo and behold, I get the same exact result... performed getting called twice, for context.control.displayName == "W"

    My question is this: how do I check for the actual key being pressed using an input action set to value? I still want the functionality of having the values get split nicely when moving diagonally but I also don't want my animation triggers firing twice if I hold a key. Right now, if I hit right, then hit up while holding right, then release right, while still holding up, my animator.SetTrigger() gets fired twice, making me roll right again long after I initially pressed it.


    EDIT: Okay, so I've tried this with a Vector2 composite (button) instead of the 'value' setting and I'm getting the same results.

    With a vector2 button input action mapped to WASD, if I press and hold D, press W, then release D, and finally release W, I get 2 performed calls for D, and one for W in this order:

    D
    W
    D

    Why? In my mind, I should get 1 performed call for each button press, and 1 canceled call for each release...

    Here is the full breakdown on the same keypress sequence:
    Code (Boo):
    1. // D STARTED    (initial press of d key)  (1, 0, 0)
    2. // D PERFORMED  (initial press of d key)  (1, 0, 0)
    3. // W PERFORMED  (initial press of w key)  (.7, .7, 0)
    4. // D PERFORMED  (RELEASE of d key)        (0, 1, 0)
    5. // W CANCELED   (release of w key)        (0, 0, 0)
    I can't make sense of this. If you press a key, you get a started call... and you will always get a performed call on the first key you press, but if you press another key while holding it, you won't get a canceled call for releasing the first key... instead you will get another performed call...

    So if I start out with D to roll right, I need the animation to trigger on started to only trigger once. But if I start with holding W, and press D afterwards, it will only trigger on performed, and it will trigger twice every time.
     
    Last edited: Sep 16, 2020
  2. djweaver

    djweaver

    Joined:
    Jul 4, 2020
    Posts:
    105
    Code (CSharp):
    1.         public void OnMove(InputAction.CallbackContext context)
    2.         {
    3.             coords = context.ReadValue<Vector2>();
    4.             if (context.started)
    5.             {
    6.                 print(context.control.displayName + " STARTED");
    7.                 //SetMoveState(true);
    8.             }
    9.             else if (context.performed)
    10.             {
    11.                 print(context.control.displayName + " PERFORMED");
    12.                 //if (context.control.displayName == "D") animator.SetTrigger("rollRight");
    13.                // State.moveDirection = new Vector3(coords.x, coords.y, 0f);
    14.             }
    15.             else if (context.canceled)
    16.             {
    17.                 print(context.control.displayName + " CANCELED");
    18.                 //State.moveDirection = Vector3.zero;
    19.                 //SetMoveState(false);
    20.             }
    21.         }
     
  3. djweaver

    djweaver

    Joined:
    Jul 4, 2020
    Posts:
    105
    I gave up and just created separate actions with the same A/D keys specifically for triggering the strafing animations. Hopefully someone who knows more than me can splain this one to me