Search Unity

Bug Actions are not triggered via simulated input (QueueValueChange)

Discussion in 'Input System' started by BearCannoli, Feb 11, 2022.

  1. BearCannoli

    BearCannoli

    Joined:
    May 12, 2020
    Posts:
    9
    I'm attempting to activate an action in my ActionAsset via simulated inputs.

    Effectively, I'm executing
    Keyboard.current.wKey.QueueValueChange(1.0f)
    but when I check if the wKey on the Keyboard.current device is being pressed, I receive false. Moreover, the Move action I've bound to the W key does not get triggered.

    My action asset looks like this:
    Screen Shot 2022-02-11 at 12.33.32 AM.png

    I'm checking if the input is being received with:
    Code (CSharp):
    1. Debug.Log(Keyboard.current.wKey.isPressed);
    2. Debug.Log(myControl.Player.Move.ReadValue<Vector2>());
     
  2. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    When are those checks running? Input will need to process for the change to take effect. Meaning it generally won't be available until the next frame.

    Also, a less obvious thing with QueueValueChange is that it basically snapshots the *current* state of the device, changes that one control and then send of the full state. But since those state changes only take effect in the upcoming frame, queuing multiple value changes this way will not result in cumulative changes.
     
    BearCannoli likes this.
  3. BearCannoli

    BearCannoli

    Joined:
    May 12, 2020
    Posts:
    9
    Those checks are running in the Update() loop. The weird thing is that in version 1.0.2, the
    Keyboard.current.wKey.isPressed
    would return true but
    myControl.Player.Move.ReadValue<Vector2>()
    would return (0,0) still.

    While in version 1.3, they both return false and (0,0) respectively.

    So in the case where I wanted to simulate key presses and have my Actions from my ActionAsset trigger, what's the best approach?
     
  4. BearCannoli

    BearCannoli

    Joined:
    May 12, 2020
    Posts:
    9
    @Rene-Damm Wanted to check in and see if this is actually a bug or an improper approach to achieve this. Thanks!
     
  5. Rene-Damm

    Rene-Damm

    Joined:
    Sep 15, 2012
    Posts:
    1,779
    The approach is fine. This, for example, should work.

    Code (CSharp):
    1. public MyBehaviour : MonoBehaviour
    2. {
    3.     private Keyboard m_Keyboard;
    4.     private InputAction m_Action;
    5.     private Keyboard m_SystemKeyboard;
    6.  
    7.     void OnEnable()
    8.     {
    9.         // Kill system keyboard.
    10.         m_SystemKeyboard = Keyboard.current;
    11.         if (m_SystemKeyboard != null)
    12.             InputSystem.RemoveDevice(m_SystemKeyboard);
    13.  
    14.         m_Keyboard = InputSystem.AddDevice<Keyboard>();
    15.         m_Action = new InputAction(binding: "<Keyboard>/w");
    16.         m_Action.Enable();
    17.     }
    18.  
    19.     void OnDisable()
    20.     {
    21.         m_Action.Disable();
    22.         InputSytem.RemoveDevice(m_Keyboard);
    23.         m_Keyboard = null;
    24.         m_Action = null;
    25.  
    26.         // Re-add system keyboard.
    27.         if (m_SystemKeyboard != null)
    28.             InputSystem.AddDevice(m_SystemKeyboard);
    29.     }
    30.  
    31.     void Update()
    32.     {
    33.         // Toggle W key.
    34.         var state = default(KeyboardState);
    35.         state.Set(Key.W, !m_Keyboard.wKey.isPressed);
    36.         InputSystem.QueueStateEvent(m_Keyboard, state);
    37.  
    38.         // The event will only surface in the *next* update. So, the following value
    39.         // will always be the opposite of the state that we just queued as an event.
    40.         Debug.Log($"Action={m_Action.IsPressed()}");
    41.     }
    42. }
    43.