Level Progression
Use this skill when the game needs multiple levels, scene transitions, saving progress, or any progression system.
Trigger Phrases
- •"multiple levels", "next level", "level 2"
- •"save", "load", "progress", "checkpoint"
- •"unlock", "locked level"
- •"scene transition", "go to next scene"
- •"main menu", "level select"
- •"game over screen", "restart"
Core Components
1. GameManager (Persistent Singleton)
csharp
// GameManager.cs - Survives scene loads
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
// Progress data
public int currentLevel = 1;
public int highestUnlockedLevel = 1;
public int totalScore = 0;
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
LoadProgress();
}
else
{
Destroy(gameObject);
}
}
// Scene Management
public void LoadLevel(int levelNumber)
{
currentLevel = levelNumber;
SceneManager.LoadScene("Level" + levelNumber);
}
public void LoadLevel(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
public void NextLevel()
{
currentLevel++;
if (currentLevel > highestUnlockedLevel)
{
highestUnlockedLevel = currentLevel;
SaveProgress();
}
LoadLevel(currentLevel);
}
public void RestartLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
public void LoadMainMenu()
{
SceneManager.LoadScene("MainMenu");
}
// Save/Load using PlayerPrefs
public void SaveProgress()
{
PlayerPrefs.SetInt("HighestLevel", highestUnlockedLevel);
PlayerPrefs.SetInt("TotalScore", totalScore);
PlayerPrefs.Save();
}
public void LoadProgress()
{
highestUnlockedLevel = PlayerPrefs.GetInt("HighestLevel", 1);
totalScore = PlayerPrefs.GetInt("TotalScore", 0);
}
public void ResetProgress()
{
PlayerPrefs.DeleteAll();
highestUnlockedLevel = 1;
totalScore = 0;
currentLevel = 1;
}
}
2. Level Complete Trigger
csharp
// LevelGoal.cs - Attach to goal/exit zone
using UnityEngine;
public class LevelGoal : MonoBehaviour
{
public float delayBeforeNext = 2f;
private bool triggered = false;
void OnTriggerEnter(Collider other)
{
if (triggered) return;
if (other.CompareTag("Player"))
{
triggered = true;
OnLevelComplete();
}
}
void OnLevelComplete()
{
// Show victory UI
Debug.Log("Level Complete!");
// Optional: Add score, show stats
// Load next level after delay
Invoke(nameof(GoToNextLevel), delayBeforeNext);
}
void GoToNextLevel()
{
GameManager.Instance.NextLevel();
}
}
3. Scene Transition Effects
csharp
// SceneTransition.cs - Fade in/out between scenes
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections;
public class SceneTransition : MonoBehaviour
{
public static SceneTransition Instance;
public Image fadeImage;
public float fadeDuration = 0.5f;
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
public void TransitionToScene(string sceneName)
{
StartCoroutine(DoTransition(sceneName));
}
IEnumerator DoTransition(string sceneName)
{
// Fade out
yield return StartCoroutine(Fade(0, 1));
// Load scene
SceneManager.LoadScene(sceneName);
// Fade in
yield return StartCoroutine(Fade(1, 0));
}
IEnumerator Fade(float startAlpha, float endAlpha)
{
float elapsed = 0;
Color color = fadeImage.color;
while (elapsed < fadeDuration)
{
elapsed += Time.deltaTime;
color.a = Mathf.Lerp(startAlpha, endAlpha, elapsed / fadeDuration);
fadeImage.color = color;
yield return null;
}
color.a = endAlpha;
fadeImage.color = color;
}
}
4. Level Select Screen
csharp
// LevelSelectUI.cs
using UnityEngine;
using UnityEngine.UI;
public class LevelSelectUI : MonoBehaviour
{
public Button[] levelButtons;
public Sprite lockedSprite;
public Sprite unlockedSprite;
void Start()
{
RefreshButtons();
}
void RefreshButtons()
{
int highestUnlocked = GameManager.Instance.highestUnlockedLevel;
for (int i = 0; i < levelButtons.Length; i++)
{
int levelNum = i + 1;
Button btn = levelButtons[i];
if (levelNum <= highestUnlocked)
{
// Unlocked
btn.interactable = true;
btn.GetComponent<Image>().sprite = unlockedSprite;
btn.onClick.AddListener(() => LoadLevel(levelNum));
}
else
{
// Locked
btn.interactable = false;
btn.GetComponent<Image>().sprite = lockedSprite;
}
}
}
void LoadLevel(int levelNum)
{
GameManager.Instance.LoadLevel(levelNum);
}
}
5. Checkpoint System
csharp
// Checkpoint.cs - Place at checkpoint locations
using UnityEngine;
public class Checkpoint : MonoBehaviour
{
public int checkpointID;
private static int lastCheckpoint = 0;
private static Vector3 lastCheckpointPosition;
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player") && checkpointID > lastCheckpoint)
{
lastCheckpoint = checkpointID;
lastCheckpointPosition = transform.position;
SaveCheckpoint();
Debug.Log("Checkpoint reached!");
}
}
void SaveCheckpoint()
{
PlayerPrefs.SetInt("Checkpoint_" + GameManager.Instance.currentLevel, checkpointID);
PlayerPrefs.SetFloat("CheckpointX", lastCheckpointPosition.x);
PlayerPrefs.SetFloat("CheckpointY", lastCheckpointPosition.y);
PlayerPrefs.SetFloat("CheckpointZ", lastCheckpointPosition.z);
PlayerPrefs.Save();
}
public static Vector3 GetRespawnPosition()
{
if (lastCheckpoint > 0)
return lastCheckpointPosition;
return Vector3.zero; // Default spawn
}
public static void ResetCheckpoints()
{
lastCheckpoint = 0;
}
}
// PlayerRespawn.cs - Handles player death/respawn
public class PlayerRespawn : MonoBehaviour
{
public void Respawn()
{
transform.position = Checkpoint.GetRespawnPosition();
// Reset health, etc.
}
}
Scene Setup Requirements
Build Settings
All scenes must be added to Build Settings:
code
File > Build Settings > Drag scenes in order: 0 - MainMenu 1 - Level1 2 - Level2 3 - Level3 ...
Required Scenes
MainMenu Scene:
- •Start Game button → LoadLevel(1)
- •Level Select button → LoadScene("LevelSelect")
- •Options button
- •Quit button
LevelSelect Scene:
- •Grid of level buttons
- •Back to menu button
- •Lock/unlock states
Game Scenes (Level1, Level2, etc.):
- •Player spawn point
- •Level goal trigger
- •Optional: Checkpoints
- •Pause menu (ESC)
GameOver Scene (or overlay):
- •Retry button → RestartLevel()
- •Main Menu button → LoadMainMenu()
- •Score display
Implementation Checklist
- •
Create GameManager
- •Add to first scene (MainMenu)
- •Mark as DontDestroyOnLoad
- •Initialize save system
- •
Set up scenes
- •MainMenu, LevelSelect, Level1, Level2, etc.
- •Add all to Build Settings
- •Consistent naming (Level1, Level2...)
- •
Add LevelGoal to each level
- •Trigger zone at end of level
- •Calls GameManager.NextLevel()
- •
Add transitions (optional)
- •Create UI Canvas with full-screen image
- •Add SceneTransition script
- •Use DontDestroyOnLoad
- •
Add save/load
- •Save on level complete
- •Save on checkpoint
- •Load on game start
- •
Add level select
- •Button for each level
- •Lock/unlock visuals
- •Connect to GameManager
Save Data Structure
Using PlayerPrefs (simple):
code
HighestLevel: int (1-N) TotalScore: int Checkpoint_Level1: int (checkpoint ID) Checkpoint_Level2: int ...
Using JSON file (advanced):
json
{
"highestLevel": 5,
"totalScore": 12500,
"levelScores": [1000, 2500, 3000, 2800, 3200],
"checkpoints": {
"Level1": 3,
"Level2": 2
},
"settings": {
"musicVolume": 0.8,
"sfxVolume": 1.0
}
}
Quick Setup Commands
Add basic progression to game:
- •Create GameManager object in MainMenu
- •Add GameManager.cs script
- •Create LevelGoal trigger at end of first level
- •Set up Build Settings with scenes
Add checkpoints:
- •Create empty GameObjects at checkpoint locations
- •Add Checkpoint.cs to each
- •Set unique checkpointID (1, 2, 3...)
- •Add respawn logic to player death
Add level select:
- •Create LevelSelect scene
- •Add buttons for each level
- •Add LevelSelectUI.cs
- •Connect buttons to array
Output to User
Explain simply:
- •"Your game now saves progress - when you beat a level, the next one unlocks"
- •"Added checkpoints - if you die, you respawn at the last checkpoint you touched"
- •"Created a level select screen where you can replay any level you've beaten"
- •"The game fades to black between levels for a smoother transition"