Upon completion of the first level, it loads the first level again. About completion of the first level for the second time, it loads the second level. Cannot fathom why. Posted is my code for the GameManage which tells when levels need to be loaded. Any help or guidance would be very appreciated.
using UnityEngine;
using System.Collections;
//added new using
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
public static int currentLevel = 0;
public static int coinCount;
public static int totalCoinCount;
public GameObject coinParent;
private static bool winScreen = false;
private static bool loseScreen = false;
public int winScreenWidth, winScreenHeight;
public int loseScreenWidth, loseScreenHeight;
//
public GUISkin skin;
public GUIStyle GUIStyle;
public Font f;
//
void Start()
{
totalCoinCount = coinParent.transform.childCount;
if (PlayerPrefs.GetInt ("Level Completed") > 0) {
currentLevel = PlayerPrefs.GetInt ("Level Completed");
} else {
currentLevel = 0;
}
}
public static void CompleteLevel()
{
winScreen = true;
}
public static void FailLevel()
{
loseScreen = true;
}
void LoadNextLevel()
{
Time.timeScale = 1f;
if (currentLevel < 29)
{
currentLevel += 1;
SaveGame();
//SceneManager.LoadScene(string scenePath)
SceneManager.LoadScene (currentLevel);
}
}
void SaveGame()
{
PlayerPrefs.SetInt("Level Completed", currentLevel);
}
public static void AddCoin()
{
coinCount += 1;
}
void OnGUI()
{
//
GUI.skin.font = f;
GUI.skin = skin;
GUIStyle style = new GUIStyle(GUI.skin.button);
style.fontSize = 35;
if(winScreen)
//
{
coinCount = 5;
Rect winScreenRect = new Rect(Screen.width/2 - (Screen.width *.5f/2), Screen.height/2 - (Screen.height * .3f/2), Screen.width *.5f, Screen.height *.3f);
GUI.Box(winScreenRect, "Level Completed", style);
if(GUI.Button(new Rect(winScreenRect.x + winScreenRect.width - 420 ,winScreenRect.y + winScreenRect.height -200, 250, 150), "Continue", style))
{
LoadNextLevel();
winScreen = false;
}
if(GUI.Button(new Rect(winScreenRect.x + winScreenRect.width - 420 ,winScreenRect.y + winScreenRect.height -40, 250, 150), "Quit", style))
{
SceneManager.LoadScene ("main_menu");
winScreen = false;
Time.timeScale = 1f;
}
}
if(loseScreen)
{
Rect loseScreenRect = new Rect(Screen.width/2 - (Screen.width *.5f/2), Screen.height/2 - (Screen.height * .5f/2), Screen.width *.5f, Screen.height *.5f);
GUI.Box(loseScreenRect, "You were melted =(", style);
if(GUI.Button(new Rect(loseScreenRect.x + loseScreenRect.width - 570 ,loseScreenRect.y + loseScreenRect.height -180, 250, 150), "Continue", style))
{
if(currentLevel == 0)
{
SceneManager.LoadScene ("level1");
loseScreen = false;
Time.timeScale = 1f;
} else {
SceneManager.LoadScene (currentLevel);
loseScreen = false;
Time.timeScale = 1f;
}
}
}
}
}
#1: your scene with index 0 is not the first level #2: if itâs not #1, your first level might be registered twice
To elaborate my thoughts on option #1:
First level is loaded when you enter the game from the menu (menu possible being the scene with index 0)
So in level one (which is scene with index 1), reading player prefs the first time before anything has completed returns 0. Next, you complete the level, increment the variable thatâs supposed to keep track of the level index so itâs 1 now => loading the ânext levelâ will be level with index 1, so the same level again.
Itâs essentially the inconsistent treatment of the value:
The saved value - at least from the name youâve given that entry in the PlayerPrefs - represents the completed level, hence you use 0 before anything has completed.
However, in your code you treat that value as being the âcurrentLevelâ that has to be played, hence the level is off by one.
Thatâd be more obvious if you renamed the currentLevel variable to completedLevel. Youâd immediately see that you increment completedLevel by one, save it - which is correct - and load the completedLevel again - which is no longer correct.
You are right. The main menu is index0. So when the first level (index1) is completed, it increments to index1 which is still level one which causes level 1 do be replayed even after completion. I can either change this statement below by adding an if statement (I think so?). I was thinking that, when on the main menu, hitting new game would increment the index. This is also another viable option. Posted below is the statement after winning a level. The second post is my main menu script.
Itâs still confusing with the current naming.
If you want to handle it that way, why donât you just save it as ânext levelâ or something. Then you can simply start out with value 1.
Also, is there any particular reason for using the legacy UI? The new UI is much better and you wonât need all that code to draw the elements.
Iâd strongly recommend constants for the names of the entries in the player prefs. But thatâs just a small improvement.
Ok so I took out the main menu script and made the new menu with the new UI and a script to go along with each buttons function. I still havenât figured out why level one plays twice. You said to start out with value 1. I assume You mean to change public static int currentLevel = 0; to = 1. I did and the level still plays twice so I changed it back. What else can I try? Iâm not sure what I can change in the naming to make it less confusing. Also, can you please elaborate on what you mean by recommending constants for the names of the entries in the player prefs. Iâm not sure what you mean. I reposted my game manager code in this post. Thank you!
No, I wasnât talking about the static field directly, rather about the initial value of the entry in the PlayerPrefs.
The PlayerPrefsâ getter methods also allow you to specify a default value that will be returned if the key has not yet been added.
I recommend to save the index of the next level, as this probably fits your current code the most.
So your start method might look like:
private void Start()
{
totalCoinCount = coinParent.transform.childCount;
currentLevel = PlayerPrefs.GetInt("Next Level", 1); // if the entry does not exist, return 1 as default, as we have to start with level 1
}
Now itâll start out with 1, and when you hit LoadNextLevel, the script should work as is, because you increment the value first (so itâll be 2), then save it and load the level with that exact index (level 2).
Thatâs one way to solve this, but I had already explained that earlier.
If you want to keep saving the value as âlevel completedâ, youâd simply need to increment the loaded value by one before you use it to load the next level.
In regards to the constants, whenever you use literal values such as the âCompleted Levelâ string, youâd be better of declaring it as constant, for example:
If you do that throughout your code, you can change the key easily in that one single line and there wonât be any inconsistencies or typos in your code.