[Solved] Level Manager Script

i want to write a function which do a restart to level scene ,
all my attempts failed to write the proper code for this restart function ,
this function called from the lose scene so it keep restarting the lose scene but actually i want it to restart the scene which the player lost the game
i used the following code
the code:


int ActiveSceneIndex;
void Update() {
ActiveSceneIndex = SceneManager.GetActiveScene ().buildIndex;
}

void Restart()
{
SceneManager.LoadScene(ActiveSceneIndex);
}

Hi @Kamal_Ezz-eldin,

Looking at your Restart() method I would suggest you are almost there.

You are using a variable called ActiveSceneIndex which is populated with the build index of the current scene.

So, when you lose in the game, you are taken to the lose scene, and then your code grabs the build index of that scene and tries to load it again.

So, that’s the problem, what can we do to fix it? Well, first of all, let’s not have that ActiveSceneIndex variable being populated every frame in the Update() method, that’s fairly inefficient.

You could store/calculate the last level played, but it would probably be easier to approach it from the other direction, e.g. store the build index of the last level completed, that way, you can just increment by one and you should get the level you need.

I’m not sure what stage you are at in the BlockBreaker project, so rather than giving you a complete script, which may include code you’ve not started in the lectures yet, I’ll give you some bits to add to what you currently have.


LevelManager.cs

using UnityEngine;
using UnityEngine.SceneManagement;

public class LevelManager : MonoBehaviour
{
    // the build index of the last completed level
    private static int lastCompletedLevel = 0;

    /// <summary>
    /// Determines whether the next level should be loaded
    /// </summary>
    public void BrickDestroyed()
    {
        if (Brick.breakableCount <= 0)
        {
            lastCompletedLevel = SceneManager.ActiveScene().buildIndex;
            LoadNextLevel();
        }
    }

    /// <summary>
    /// Loads the level which the player has not yet completed
    /// </summary>
    private void RestartUncompletedLevel()
    {
        SceneManager.LoadScene(lastCompletedLevel++);
    }
}


Obviously include you other methods as well.

What I have added is a private static variable to the LevelManager, there will be only one instance of this variable as it is a member of the class, not the instance of the class.

When the BrickDestroyed() method is called, a check is currently performed to see if all of the bricks have been destroyed, if they have, it calls LoadNextLevel() which, because of the requirement to have your playable scenes before the Win and Lose scenes resepectively, happens to work. What I have added before the next scene is loaded (whether it’s playable or the win scene) is the population of the lastLevelCompleted variable with the build index of the current scene the player just completed.

When you make a call to the RestartUncompletedLevel() method, it gets the value of that variable and increments it by one, as an example;

  • assuming your Start scene is build index 0 (zero), then…
  • the player starts the game, the next scene is loaded (build index 1)
  • the player completes Level_01, the lastCompletedLevel value is set to 1, the next scene is loaded (build index 2)
  • the player completes Level_02, the lastCompletedLevel value is set to 2, the next scene is loaded (build index 3)
  • the player loses, you load the lose scene and display a button “Restart”
  • the player clicks on the “Restart” button which calls the RestartUncompletedLevel() from your LevelManager
  • RestartUncompletedLevel() takes the value of the lastCompletedLevel, 2, and increments it by 1, making 3, it then loads the scene with the build index of 3

Note, this is off the top of my head and thus untested. Let me know how you get on.

The one downside of using the static variable will be that whilst your game is running, the value will be persistent, as such you will need to add some functionality to reset it when the player is on the Start scene, otherwise they will be taken to the incorrect level to restart from when they lose in a subsequent game.

I can’t remember how the game is actually launched, I think it’s from the “Start” button and then you call the LoadLevel() method, passing in “Level_01” as the parameter? If that’s the case you could change that to call a method called BeginGame() and add this code to LevelManager;

public void BeginGame()
{
    lastCompletedLevel = 0;

    LoadLevel("Level_01");
}

It’s not ideal having the name of the first level hard coded like that, but in this simple example isn’t really any different to having it hard coded as a parameter in the OnClick event for the “Start” button, leaves room for you to further improve.

I hope this helps, let me know either way :slight_smile:

p.s. I renamed your method RestartLevel() to RestartUncompletedLevel() deliberately, you can of couse call them what ever you want, but potentially by doing this, you could still use RestartLevel() to let the player return to any previous level if you extended it to take in an integer value for a level they had completed. Additionally, you may want to add a Restart() method which just starts the game all over again.

thanks @Rob for this great explanation but there is something wrong i applied what you have mentioned in your reply ,Now when i click the restart button it doesn’t loop the lose scene as it was before, it loads another level but not the right level
i noticed that there is something wrong with ( BreakableCounter ) for Example : When i lose the game and there are 5 bricks left when i press on the restart level button it load another level but the ( BreakableCounter ) Doesn’t reset it continue add the new level bricks to the 5 bricks left from the lose level and that mean that there is no win situation in this level .

_ Another thing i wanna ask what if the player lost in level 1 so there is no lastCompletedLevel .

_there is a bit different in my game scenes order i added a scene board with numbers this numbers are actually buttons each number load new level

-this is my scene index

_Here is a link for my LevelManager.cs gitHub link for my LevelManager
_ I know that my questions are kinda noob questions, im totally new to the programming.
_ Thanks for your valuable time.

1 Like

Now when i click the restart button it doesn’t loop the lose scene as it was before, it loads another level but not the right level i noticed that there is something wrong with ( BreakableCounter ) for Example : When i lose the game and there are 5 bricks left when i press on the restart level button it load another level but the ( BreakableCounter ) Doesn’t reset it continue add the new level bricks to the 5 bricks left from the lose level and that mean that there is no win situation in this level .

Ah! Of course, in the original LoadLevel() and LoadNextLevel() methhods you’d have had something like this;

    /// <summary>
    /// Loads the next level in the scene build index order
    /// </summary>
    public void LoadNextLevel()
    {
        Brick.breakableCount = 0;

        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex +1);
    }

So, what’s happening is because the breakableCount variable is static, it persists, which is great - unless you forget to reset it - like I did in my reply to you! :slight_smile:

So, in the RestartUncompletedLevel() method, just add that line before the call to load the desired level, e.g.;

    /// <summary>
    /// Loads the level which the player has not yet completed
    /// </summary>
    private void RestartUncompletedLevel()
    {
        Brick.breakableCount = 0;

        SceneManager.LoadScene(lastCompletedLevel++);
    }

> Another thing i wanna ask what if the player lost in level 1 so there is no lastCompletedLevel .

Another good point. So you need to consider edge cases, e.g. what happens if they lose on the first level when there isn’t a previously completed level.

What we want to do is set a default value to lastCompletedLevel so that it corrects this issue. I had set it to 0 (zero) because I didn’t appreciate you had the level select scene, I believe in the original game there was the Start scene (index 0) then Level_01 (index 1), so by starting with the value set to zero, when we increment it the edge case was covered.

All we need to do is increment our default value by one and I think that will resolve that for you.

    // the build index of the last completed level
    private static int lastCompletedLevel = 1;

You could of course also cover this with some logic (if / else etc) before calling the LoadScene() method within RestartUncompletedLevel() but it isn’t going to make a lot of difference really.

I think the above will resolve the issues you’ve mentioned - let me know :slight_smile:

1 Like

@Rob Thanks dude
after i added this few changes to NextLevel () and RestartUnCompletedLevel()
both functions working fine now

Your help is much appreciated.

1 Like

You’re very welcome :slight_smile:

Privacy & Terms