Unlock Levels

Hi all! What I’m trying to accomplish isn’t too hard, but what I need is some direction in how to unlock levels. Right now, I have 5 levels, and 4 of them will be locked except the first like so:

( ) (X) (X) (X) (X)

After the events of level 1 is complete, I was thinking of there being some variable to unlock the second level(which is no problem, and save that variable using PlayerPrefs(which again, is no problem). I was thinking of incrementing a player prefs var like:

//Goes in the levels
function Check(){
     if(objectives are complete){
         unlock++;
     }
}
static var unlock : int;

function Awake(){
     unlock = PlayerPrefs.GetInt("Unlock", 0);
}

function Start(){
     if(unlock > 1){
          //Unlock next level...
     }
     if(unlock > 2){
          //Unlock next level...
     }
}

( ) ( ) (X) (X) (X)

I guess the problem is that for my game, there is replayability. So, the player is able to stop playing, go to this level selection screen, and replay any level he’s unlocked already. However, the player can keep playing, lets say, lvl1, and the the prefs var will increment, unlocking levels instead of going through the game and unlocking them.

Do you see where I’m trying to get at? Am I on the right path at least?

It seems like you would just add a condition in the check function:
if(objectives are complete thisLevel == unlock)unlock++;

Do you have some mechanism for tracking the current level number?

You may be able to use Application.loadedLevel if your levels are listed sequentially in build settings. If not, you could homebrew a pretty simple static variable, much like you’ve done with unlock.

With that done, you just need to check if the current level ID is less than your current unlock ID. If it is, don’t increment unlock.

    bool objectivesComplete = ...
    int unlock = ...
    int currentLevel = ...
    if (objectivesComplete  unlock <= currentLevel) {
        unlock++;
    }

Cool. I’ll have to play around with this tomorrow…there’s still a few concerns.

Ok. I messed around a bit with this:

This script unlocks the levels. Now, this is a 3D menu selection screen with 3D models and planes. To select a level, the player will have to click the plane with the level’s picture on it, but in front of each level select option is another plane with a mesh collider on it called lock, which restricts the player from loading that level whenever it’s clicked. This script takes care of removing those locks, and also letting the player replay all the levels he has unlocked previously:

private var lock1 : GameObject;
private var lock2 : GameObject;
private var lock3 : GameObject;
private var lock4 : GameObject;

static var unlock : int;

function Awake(){
	unlock = PlayerPrefs.GetInt("Unlock",0);
}

function Start(){
lock4 = GameObject.Find("Lock4");
lock3 = GameObject.Find("Lock3");
lock2 = GameObject.Find("Lock2");
lock1 = GameObject.Find("Lock1");
	if(unlock >= 1){
		Destroy(lock1);
	}
	if(unlock >= 2){
		Destroy(lock2);
	}
	if(unlock >= 3){
		Destroy(lock3);
	}
	if(unlock >= 4){
		Destroy(lock4);
	}
}

I didn’t make 5 scenes, but I made one scene and attached this to a cube:

static var unlock : int;

function Awake(){
	unlock = PlayerPrefs.GetInt("Unlock",0);
}

function OnTriggerEnter(other : Collider){
	if(other.tag == "Player"){
		unlock++;
		PlayerPrefs.SetInt("Unlock",unlock); 
	}
}

But of course, there is replayability in this game, so the player can replay chapter1 after he has unlocked chapter 2, and once he’s finished with chapter 1 again, variable “unlock” increments, unlocking chapter 3 without having to play chapter 2, and so on. Is there a way I could do this instead of increasing the unlock var?

The first thing you need is something ot make your game aware of which level is currently loaded.

  • If all of your levels are in the same scene then create an object in your menu that persists when you load your level scene (search for DontDestroyOnLoad)
    • Give that persistent object a script that holds an integer called current level.
    • When the user selects a level set that integer to the appropriate value.

Next use this to unlock levels at the appropriate time

  • Create a playerprefs variable that tracks how many levels are unlocked i.e unlockedCount
  • Create a playerprefs variable that tracks how many levels have been beaten i.e. completeCount
  • Now when the level is complete check to see if the current level number is higher than the completeCount number, this means that you are beating the level for the first time and should increment unlockedCount. Otherwise don’t do anything.

Let me know if you need me to explain something more clearly.

I don’t quite get the last bullet point. I think what I was looking for is what you mentioned, where the game understands that, for example, when the player goes through chapter 1 for the first time, it is the FIRST TIME throughout the entire game until “New Game” is selected, and if the player decides to replay through ch.1 the second time, it wont count.

Perhaps I can create a seperate PlayerPrefs that goes along with each chapter. So(and I’m just jotting ideas for you guys), if the player goes through that trigger, then unlock++ and PlayerPrefs.SetString(“Chapter1”);. Then…

if(unlock >= 1){
     if(PlayerPrefs.HasKey("Chapter1")){
		          //Do yo' thang...
		}
}

What about that?

Yes I guess at the very basic level what you want to do is

if(level is beaten for the first time){
unlock next level
}

I was trying a different approach on it with PlayerPrefs.GetString and SetString, but I don’t think it worked. Any help?

function OnTriggerEnter(other : Collider){
     if(other.tag == "Player"){
          PlayerPrefs.SetString("Unlock", "Chapter2");
     }
}

In the level selection screen…

private var lock1 : GameObject;
private var lock2 : GameObject;
private var lock3 : GameObject;
private var lock4 : GameObject;

function Start(){
lock4 = GameObject.Find("Lock4");
lock3 = GameObject.Find("Lock3");
lock2 = GameObject.Find("Lock2");
lock1 = GameObject.Find("Lock1");

	if(PlayerPrefs.HasKey("Chapter2")){
		Destroy(lock1);
	}
}

I figured it out. Whenever a chapter/objective of the game is complete, this is called:

PlayerPrefs.SetString("Chapter 2","Level Name2");

It unlocks/removes the planes like this:

	if(PlayerPrefs.HasKey("Chapter 2")){
		Destroy(lock1);
	}

Each SetString must come with a different chapter name and a different level name.

Thank You! :slight_smile: