Actions are not triggered via simulated input (QueueValueChange)

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:

I’m checking if the input is being received with:

Debug.Log(Keyboard.current.wKey.isPressed);
Debug.Log(myControl.Player.Move.ReadValue<Vector2>());

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.

1 Like

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?

@Rene-Damm Wanted to check in and see if this is actually a bug or an improper approach to achieve this. Thanks!

The approach is fine. This, for example, should work.

public MyBehaviour : MonoBehaviour
{
    private Keyboard m_Keyboard;
    private InputAction m_Action;
    private Keyboard m_SystemKeyboard;

    void OnEnable()
    {
        // Kill system keyboard.
        m_SystemKeyboard = Keyboard.current;
        if (m_SystemKeyboard != null)
            InputSystem.RemoveDevice(m_SystemKeyboard);

        m_Keyboard = InputSystem.AddDevice<Keyboard>();
        m_Action = new InputAction(binding: "<Keyboard>/w");
        m_Action.Enable();
    }

    void OnDisable()
    {
        m_Action.Disable();
        InputSytem.RemoveDevice(m_Keyboard);
        m_Keyboard = null;
        m_Action = null;

        // Re-add system keyboard.
        if (m_SystemKeyboard != null)
            InputSystem.AddDevice(m_SystemKeyboard);
    }

    void Update()
    {
        // Toggle W key.
        var state = default(KeyboardState);
        state.Set(Key.W, !m_Keyboard.wKey.isPressed);
        InputSystem.QueueStateEvent(m_Keyboard, state);

        // The event will only surface in the *next* update. So, the following value
        // will always be the opposite of the state that we just queued as an event.
        Debug.Log($"Action={m_Action.IsPressed()}");
    }
}