3

In Unity, I manage to go back to the last scene by clicking the Device Android back button but the problem is when I am in the 3rd scene and I want to go back to 2nd and then back to 1st scene.

From 3rd to 2nd scene, when I click back button it goes successfully but when I press the back button again from 2nd scene to 1st scene it doesn't go. It looks like that the back button works only for the first time.

Here is my c# code:

public class SceneLoader : MonoBehaviour
{
    private float seconds = 0.5f;
    private static int lastScene;
    private int currentScene;

    private void Awake()
    {
        currentScene = SceneManager.GetActiveScene().buildIndex;
    }

    private void Update()
    {
        BackButtonPressed();
    }

    public void LoadNextScene(int numberOfSceneToLoad)
    {
        StartCoroutine(LoadScene(numberOfSceneToLoad));    
    }

    private IEnumerator LoadScene(int numberOfScene)
    {
        currentScene = SceneManager.GetActiveScene().buildIndex;
        SetLastScene(currentScene);

        yield return new WaitForSeconds(seconds);
        SceneManager.LoadScene(numberOfScene);

    }


    private void BackButtonPressed()
    {
        if (Input.GetKey(KeyCode.Escape))
        {
            Debug.Log("Current scene: " + currentScene);
            Debug.Log("Last Scene (scene to load): " + GetLastScene());

            SceneManager.LoadScene(GetLastScene());

            currentScene = GetLastScene();
            Debug.Log("Now the Current scene is: " + currentScene);    
        }
    }


    public static void SetLastScene(int currentSceneToLastScene)
    {
        lastScene = currentSceneToLastScene;
    }

    public static int GetLastScene()
    {
        return lastScene;
    }

    public void QuitGame()
    {
        Application.Quit();
    }

}

Thanks in advance.

Johny
  • 625
  • 2
  • 6
  • 26

4 Answers4

3

When you go BackToLastScene you set currentScene = GetLastScene(); but never change lastScene value.

I suggest you use some sort of LIFO data structure like Stack from System.Collections to keep track of the scenes.

Here's a sample pseudo-code:

define scene_stack;
function LoadNewScene(new_scene){
    current_scene = GetCurrentScene();
    scene_stack.Push(current_scene);
    LoadScene(new_scene);
}

function LoadOldScene(){
    old_scene = scene_stack.Pop();
    LoadScene(old_scene);
}
  • 1
    Thank you for the answer Damiano. I used the lastScene -= lastScene inside BackButtonPressed() just after loading the scene and it seems to work but it needs more testing. – Johny Nov 29 '18 at 15:30
  • Keep in mind that decrementing the scene works as long as you don't have to skip scenes and traverse them always one by one. The Stack approach is more solid in this regard since it lets you load the last scene regardles off its id. Still it is not necessary if your application does not need it. (Sorry for my bad english) – Damiano Caprari Nov 29 '18 at 16:18
  • Yes you are right. For my current game I just need to go back to main screen without skipping the "important scenes" but I think your approach is better if you need to follow the exact path that you follow. – Johny Nov 29 '18 at 21:29
2

After the help from @Damiano, I changed the my code like this and it works:

public class SceneLoader : MonoBehaviour
{
    private float secondsToLoadNextScene = 0.5f;
    private static int lastScene;
    private int mainScene = 1;
    private int currentScene;

    public static Stack<int> sceneStack = new Stack<int>();


    private void Awake()
    {
        currentScene = SceneManager.GetActiveScene().buildIndex;
    }

    private void Update()
    {
        BackButtonPressed();
    }

    public void LoadNextScene(int numberOfSceneToLoad)
    {
        StartCoroutine(LoadScene(numberOfSceneToLoad));
    }

    private IEnumerator LoadScene(int numberOfScene)
    {
        SetLastScene(currentScene);

        yield return new WaitForSeconds(secondsToLoadNextScene);
        LoadNewScene(numberOfScene);
    }

    public void BackButtonPressed()
    {
        if (Input.GetKey(KeyCode.Escape) && currentScene > mainScene)
        {
            if (lastScene == 0)
            {
                Debug.Log("Last scene was Splash Screen so load Main Scene instead.");
                SceneManager.LoadScene(mainScene);
            }
            else
            {
               LoadLastScene();                    
            }         
        }
    }

    public void LoadNewScene(int sceneToLoad)
    {
        currentScene = SceneManager.GetActiveScene().buildIndex;
        sceneStack.Push(currentScene);
        SceneManager.LoadScene(sceneToLoad);
    }

    public void LoadLastScene()
    {
        lastScene = sceneStack.Pop();
        SceneManager.LoadScene(lastScene);
    }

    public static void SetLastScene(int makeCurrentSceneTheLastScene)
    {
        lastScene = makeCurrentSceneTheLastScene;
    }

    public static int GetLastScene()
    {
        return lastScene;
    }    

}
Johny
  • 625
  • 2
  • 6
  • 26
  • Hey. I used this script with a dont destroy on load function and put it in a gameobject at the first scene. How should I load some other scene from some other script? – Abhijeet Sridhar Dec 28 '19 at 10:21
1

This worked for me:

public class ChangeScene : MonoBehaviour
{
public static Stack<int> scenes = new Stack<int>();
  int numScenes = scenes.Count;
public void loadScene(int newScene)
  {
    scenes.Push(newScene);
    SceneManager.LoadScene(newScene);
  }
public void previousScene()
  {
    if (numScenes != 0 && numScenes != 1)
    {
      scenes.Pop();
      SceneManager.LoadScene(scenes.Peek());
    }
    else if (numScenes == 1)
    {
//go back to main Scene
      loadScene(0);
    }
  }
}
0

I spent a lot of time searching for this topic so I came up with this implementation since I found that most solutions are complicated. I came from a native android background so I implemented what native android does which is using a stack for the activities opened. this code also quits the application when you press the back button while in the main screen.

public class navigation : MonoBehaviour
{
   public static Stack<string> scenes = new Stack<string>();

   void Start()
   {
        if (scenes.Count == 0)
        {
            scenes.Push(SceneManager.GetActiveScene().name);
        }
    }

    void Update()
    {
        previousScene();
    }

    public void previousScene()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
           if (scenes.Count == 1)
            {
                Application.Quit();
            }
            else
            {
                scenes.Pop();
                string sceneToBuild = scenes.Pop();
                loadScene (sceneToBuild);
            }
        }
    }

    public void loadScene(string newScene)
    {
        scenes.Push (newScene);
        SceneManager.LoadScene (newScene);
    }
}