Search Unity

InputAction internal state seems inconsistent after a scene reload

Discussion in 'Input System' started by pitchblende, Feb 24, 2021.

  1. pitchblende

    pitchblende

    Joined:
    Jan 9, 2020
    Posts:
    71
    I'm using Unity Input System v1.0.2 with Unity 2019.4.20f1 (LTS).

    I have a simple button on a USB joystick that is designed to be held down when a scene loads (it is part of a custom-built controller and used to select a vehicle transmission mode). When the scene initially loads, this already-depressed button is properly detected as such and everything works.

    My application has a way to reset the current scene and start from scratch. But when I reload the same scene with:

    Code (CSharp):
    1.         Scene scene = SceneManager.GetActiveScene();
    2.         SceneManager.LoadScene(scene.buildIndex, LoadSceneMode.Single);
    ... the already-depressed button state is not correctly detected. The Input System Debugger shows the button as still active, but the API does not. In InputAction.ReadValue(), the variable
    actionStatePtr->controlIndex
    has the value -1, which is considered to be an invalid index.

    Secondly, somewhat aside from this, why does this work for a button Action:

    Code (CSharp):
    1. System.Convert.ToBoolean(buttonAction.ReadValue<float>())
    (returns true if button is pressed)

    But this does not:

    Code (CSharp):
    1. buttonAction.ReadValue<bool>();
    (always returns false)

    (EDIT: for some reason the Forum thinks my edits are spam...)
     
  2. pitchblende

    pitchblende

    Joined:
    Jan 9, 2020
    Posts:
    71
    I've written a short script that can be applied to a fresh scene with a single Empty, and demonstrates this behaviour.

    To reproduce, create a fresh scene with a single Empty and add this script to it, then create two Button action bindings (set them both to Action Type "button" not "value"). The Button Action is for the Joystick button (but perhaps it will work with keyboard keys too - still trying combinations myself), the Reload Action can just be bound to, say, spacebar, to reload the scene on-demand.

    Hold down the joystick button and start the Player. When it starts, you'll see that both OnEnable() and Update() see the correct button state according to console messages. Without letting go of the button, press the Reload button you've chosen and the scene should immediately reload. Observe that the console now reports that Input System believes the button bound to Button Action is no longer pressed, but it is!

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class InputSystemBug : MonoBehaviour
    6. {
    7.     [SerializeField] private InputAction buttonAction;
    8.     [SerializeField] private InputAction reloadAction;
    9.  
    10.     private bool reloadScene = false;
    11.    
    12.     private void OnEnable()
    13.     {
    14.         reloadAction.started += ctxt => reloadScene = true;
    15.  
    16.         buttonAction.Enable();
    17.         reloadAction.Enable();
    18.        
    19.         print("OnEnable: " + System.Convert.ToBoolean(buttonAction.ReadValue<float>()));
    20.     }
    21.  
    22.     private void OnDisable()
    23.     {
    24.         buttonAction.Disable();
    25.         reloadAction.Disable();
    26.     }
    27.  
    28.     private void Update()
    29.     {
    30.         print("Update: " + System.Convert.ToBoolean(buttonAction.ReadValue<float>()));
    31.  
    32.         if (reloadScene)
    33.         {
    34.             Scene scene = SceneManager.GetActiveScene();
    35.             SceneManager.LoadScene(scene.buildIndex, LoadSceneMode.Single);
    36.         }
    37.     }
    38. }
     
  3. pitchblende

    pitchblende

    Joined:
    Jan 9, 2020
    Posts:
    71
    Another observation - if I change the buttonAction's Action Type to "Value" and Control Type to "Any", then only the
    OnEnable()
    function sees a false value -
    Update()
    sees the correct value from the first frame after a scene reload. If I switch back to Action Type "Button" the problem resurfaces.

    What's the difference between Action Type "Button" and "Value" for a button anyway? It seems they behave almost the same way, except in this situation.