Input between scenes; is there a solution yet?

When you switch scenes while holding an input down, that input will be set to 0 in the next scene. That means if you’re not specifically working your game around so that your player releases the movement keys, they’ll stop until the player re-taps the keys, which in some cases can completely kill the momentum of the game.

There are three solutions that seem to float around.

1: Import user32.dll on Windows

[DllImport("user32.dll")]
public static extern short GetAsyncKeyState(int vkey);

void Update() {
    if ( GetAsyncKeyState(0x25 & 8000) > 0)
        Debug.Log("Left key pressed");
}
  • It is hacky to import a DLL for input only
  • You need to know the key codes ahead of time (they’re constants, so not a really big problem)
  • No gamepad support
  • Kills cross-platform compatibility

2: Use additive loading and unload the previous scene

void Update(){
    velocity.x = Input.GetAxisRaw("Horizontal");
    // Same happens with Input.GetKey().
    if(shouldNewSceneLoad) {
        SceneManager.LoadScene(newScene, LoadSceneMode.Additive);
        SceneManager.UnloadSceneAsync(oldScene);
    }
}
  • Causes weird issues where the old scene won’t be unloaded because Unity still thinks it’s the active scene
  • Also happens if I set the active scene with SceneManager.SetActiveScene().

3: Put everything in one scene, just far apart

  • Editing this becomes a mess
  • Completely defeats the purpose of scenes as self-contained levels

I’m currently using method 1, but have there been any better ways to handle this since mid-2018? I did try the new Input system, but it doesn’t seem to work in 2019.2.11f1 (perhaps because 2019.2.12 came out?).

2 Likes

I had same problem. I tried additive scene loading. Its work but created bad side effects for my project. So i write this script that first unloading old scene later load additive new scene.

    public void load(string scene) {
        var temp = SceneManager.CreateScene("temp");
        SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene()).completed += i => {
            SceneManager.LoadSceneAsync(scene, LoadSceneMode.Additive).completed += j => {
                SceneManager.SetActiveScene(SceneManager.GetSceneByName(scene));
                SceneManager.UnloadSceneAsync(temp);
            };
        };
    }
1 Like