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

Input.GetKey() reset on Load Scene

Discussion in 'Editor & General Support' started by Vermonde, Jul 11, 2012.

  1. Vermonde

    Vermonde

    Joined:
    Apr 6, 2011
    Posts:
    1
    Hey there,
    I stumbled in a problem recently and can't find a way around it.


    If I load a scene while holding a key the Input.GetKey( ) method stops working.

    It returns false until I "release and press" the key down again.

    This is particularly bad for the current game I'm working on.
    It's a 2D top down game with lots of small scenes (each is a room in the game). The character can walk in "stealth mode" while holding the 'S' key but if I change room while in "stealth mode" the Input detection stops and the character start running again. Then the player have to "release and press" the stealth key again.

    That's pretty annoying for the game flow
    =(

    anyone know a way around it?
     
    jrsvd, kristevalex and Rodolfo-Rubens like this.
  2. Butterworth

    Butterworth

    Joined:
    Aug 8, 2012
    Posts:
    25
    I have a similiar problem. I want the user to be able to launch the game holding down the shift or control key to indicate they want a special dialog to popup before actually launching the game. It doesnt seem to work unless I press the key immediately after launching the game.

    Does anyone understand why this problem occurs and if there is a solution?
     
  3. joedurb

    joedurb

    Joined:
    Nov 13, 2013
    Posts:
    38
    I found this thread while attempting to find solution, So I figured to update even if old.
    This is likely a new function since question asked:

    Input.ResetInputAxes();

    Fixed my problems with Input.GetKey being stale.
     
  4. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    ResetInputAxes() didn't solve my issue here...
     
  5. Krotux

    Krotux

    Joined:
    Apr 1, 2016
    Posts:
    4
    Any update on this issue?
     
  6. Khena_B

    Khena_B

    Joined:
    Aug 21, 2014
    Posts:
    273
    This is a huge problem for my project, i'm considering some big changes which aren't part of my design choices just to get around this issue.
     
  7. Khena_B

    Khena_B

    Joined:
    Aug 21, 2014
    Posts:
    273
    I found a way to make this work, people were suggesting to use LoadSceneMode.Additive, it seemed like a complicated workaround but it really wasn't, the idea is to load the next scene additively and unload the previous scene right after so that there is never an "in between scenes" state.

    Something like:

    Code (CSharp):
    1. string currentScene = SceneManager.GetActiveScene().name;
    2.  
    3. asyncOperation = SceneManager.LoadSceneAsync(nextLevel, LoadSceneMode.Additive);
    4.  
    5. asyncOperation.allowSceneActivation = true;
    6.  
    7. yield return asyncOperation;
    8.  
    9. SceneManager.UnloadScene(currentScene);
    10.  
     
    HCrowley and Deleted User like this.
  8. Deleted User

    Deleted User

    Guest

    Had this issue too, KhenaB's solution worked but to clarify here's how to implement it, note that briefly both scenes will be loaded at the same time so you may want to add a fade in and out on load to your UI to hide any weirdness this creates:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class Load_On_Trigger : MonoBehaviour {
    6.  
    7.     public string level;
    8.  
    9.     AsyncOperation asyncOperation;
    10.  
    11.     private void OnTriggerEnter2D(Collider2D collision)
    12.     {
    13.         StartLoading();
    14.     }
    15.     public void StartLoading()
    16.     {
    17.         StartCoroutine("load");
    18.     }
    19.  
    20.     IEnumerator load()
    21.     {
    22.         string currentScene = SceneManager.GetActiveScene().name;
    23.         asyncOperation = SceneManager.LoadSceneAsync(level, LoadSceneMode.Additive);
    24.         asyncOperation.allowSceneActivation = true;
    25.         yield return asyncOperation;
    26.         SceneManager.UnloadSceneAsync(currentScene);
    27.  
    28.     }
    29. }
    30.  
    Now instead of using "void OnLevelWasLoaded(int level){}" you'll have these options set up like this in any class that needs to react to scene changes:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class Level_Change: MonoBehaviour {
    6.  
    7.     void OnEnable()
    8.     {
    9.         SceneManager.activeSceneChanged += OnSceneChange;
    10.         SceneManager.sceneLoaded += OnSceneLoaded;
    11.         SceneManager.sceneUnloaded += OnSceneUnloaded;
    12.     }
    13.  
    14.     void OnDisable()
    15.     {
    16.         SceneManager.activeSceneChanged -= OnSceneChange;
    17.         SceneManager.sceneLoaded -= OnSceneLoaded;
    18.         SceneManager.sceneUnloaded -= OnSceneUnloaded;
    19.     }
    20.     private void OnSceneLoaded (Scene scene, LoadSceneMode mode)
    21.     {
    22.       //executes when new scene is loaded
    23.     }
    24.     private void OnSceneUnloaded (Scene scene)
    25.     {
    26.       //executes when old scene is unloaded
    27.     }
    28.     private void OnSceneChange(Scene scene1, Scene scene2)
    29.     {
    30.       //executes when old scene changes to new scene
    31.     }
    32. }
     
    gaegumun and HCrowley like this.
  9. kristevalex

    kristevalex

    Joined:
    Oct 1, 2020
    Posts:
    1
    I tried this solution, but GetKey still resets, and if I use GetKeyUp & GetKeyDown while storring key state in static variable, when releasing key in new scene there is no response from GetKeyUp.
     
  10. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    This bug exists in Unity 2020.3.23f1 LTS. Input.GetKeyUp() will always fail if the key was pressed down in a previous scene. This is a big problem for me because I store button state and allow input from both keyboard and gamepad. When I click a button that takes me back to the main menu, the GetKeyUp() method is never fired.
     
  11. MikHaven

    MikHaven

    Joined:
    Jan 13, 2015
    Posts:
    7
    As this was not working for some in 2020.3 as above. I will post my solution. (Did not try the scene loading stricks above)

    TLDR; Use a toggle, since you can't control Unity.Input

    I looked at multiple threads, including an InputBroker, to handle the transactions, but that failed. Because you can't control what others 'Unity-Static-Input' is going to do. The key isn't registered across scene loads. You can PROBABLY handle all the edge cases, and override each system, to say this key is down, and if I press it again, but your still stuck in that down state, that the input will never recognize again. Which is weird as its a state change. Somehow they are only looking for keys down, to say a key is up.

    The solution I found that works out easier, is if you use a toggle. Which as is in the case above, for the Sealth Game, and that is better for the users. You toggle stealth on and off.

    Then when you switch scenes, its a matter of keeping that state information. I used player prefs to test, and that works great.

    Anyways I know its not ideal, but unless you write your own, to avoid Input, your stuck in that keystate that never registers. This seems bizarre to handle Input that way, since their are LOTS of edge cases, such as clicking off the screen, where you might want to preserve your state. OR just check for Keyup, regardless if the key was pressed down that Scene-State or not.
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    As long as you can handle having two scenes loaded at once, this is my work-around. To test it, add Scene1, Scene2 and Scene3 to your editor and off you go.

    The main work:

    Code (csharp):
    1. using UnityEngine.SceneManagement;
    2.  
    3. public static partial class SceneHelper
    4. {
    5.     // @kurtdekker - to load next scene without resetting Input axes
    6.     public static void LoadScene( string SceneNameToLoad)
    7.     {
    8.         PendingPreviousScene = SceneManager.GetActiveScene().name;
    9.         SceneManager.sceneLoaded += ActivatorAndUnloader;
    10.         SceneManager.LoadScene( SceneNameToLoad, LoadSceneMode.Additive);
    11.     }
    12.  
    13.     static string PendingPreviousScene;
    14.     static void ActivatorAndUnloader( Scene scene, LoadSceneMode mode)
    15.     {
    16.         SceneManager.sceneLoaded -= ActivatorAndUnloader;
    17.         SceneManager.SetActiveScene( scene);
    18.         SceneManager.UnloadSceneAsync( PendingPreviousScene);
    19.     }
    20. }
    It uses a cheesy static and thus is limited to one scene at a time but it wouldn't be hard to hack it to handle an array of additively loaded scenes as "bunches" by using the same load-then-unload process.

    scene-a-mundo.png
     

    Attached Files:

    zmaxer and jrsvd like this.