Quite bad bug where inputs without modifiers stop being read

Got a gnarly one with a simple reproduction.

If you create multiple commands, one for example for key w and one for ctrl+w, and then while reading the w input, disable the layer containing the commands, later when you re-enable the layer, the new input system won’t respond to the command mapped to ctrl+w at all until the actions/devices are manually Reset()!

My guess is the internal tracking state likely becomes corrupt when disabled.

Though in the end the repro was simple, I struggled with this one for weeks trying to understand why some commands weren’t working intermittently. Quite a nasty issue, and it’s unclear if issuing Resets that frequently is causing additional issues.

Submitted a repro as case IN-42617; the simple code to repro below (alongside an event system with a new input system component)

  1. Press ctrl+w you will see the “with modifier” command properly being read.

  2. Press w and you will see “witohut modifier” command properly being read.

  3. Press 2 to re-enable the input map.

  4. ctrl+w no longer works!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class Controller : MonoBehaviour
{
    InputActionMap map,map2;

    InputAction one,onen,sw1,sw2;
    void Start()
    {
        map = new InputActionMap();
        map2 = new InputActionMap();


        onen = map.AddAction("one", InputActionType.Button);
        onen.AddBinding("<Keyboard>/w");
        onen.AddBinding("<Gamepad>/buttonSouth");

        one = map.AddAction("one+ctrl", InputActionType.Button );
        one.AddCompositeBinding("OneModifier")
            .With("Binding", "<Keyboard>/w")
            .With("Modifier", "<Keyboard>/ctrl");
        one.AddCompositeBinding("OneModifier")
            .With("Binding", "<Gamepad>/buttonSouth")
            .With("Modifier", "<Gamepad>/leftTrigger");

        sw1 = map2.AddAction("sw1", InputActionType.Button);
        sw1.AddBinding("<Keyboard>/1");
        sw1.AddBinding("<Gamepad>/buttonWest");

        sw2 = map2.AddAction("sw2", InputActionType.Button);
        sw2.AddBinding("<Keyboard>/2");
        sw2.AddBinding("<Gamepad>/buttonNorth");

        map.Enable();
        map2.Enable();
    }

    // Update is called once per frame
    void Update()
    {
        if( sw1.WasPerformedThisFrame())
        {
            UnityEngine.Debug.Log("disable map");
            map.Disable();
        }

        if (sw2.WasPerformedThisFrame())
        {
            UnityEngine.Debug.Log("enable map");
            map.Enable();
        }

        if (one.WasPerformedThisFrame())
        {
            UnityEngine.Debug.Log("Action WITH MODIFIER (1) performed");
        }

        if (onen.WasPerformedThisFrame())
        {
            UnityEngine.Debug.Log("Action (1) performed");
            map.Disable(); // <--- Disabling it inside the update frame with this kind of rig seem to kill modifier tracking until the device/aciton is reset!
        }
    }

}
1 Like

This was confirmed by QA case IN-42617/ISXB-505

This is an extremely critical bug, because while the sample above is contrived, the case where it triggers is pretty simple in practice:

  1. press a button with a modifier that opens a new menu
  2. the new menu switches up some layers (disabling one that was used to trigger it)
  3. return to the previous menu or game view
  4. quite a lot of controls are now permanently broken!
1 Like