Keep Between Scenes
Part of the Building Real Games section of Coddy's Unity journey. Lesson 20 of 56.
Loading a scene destroys every object of the old one, but some things must last the whole game, such as the coins a player carries from level to level. DontDestroyOnLoad(gameObject) moves an object out of its scene into a scene of its own, called DontDestroyOnLoad in the Hierarchy at Play, which loads never touch. It works on a root object only: on a child, Unity logs a warning and keeps nothing. The kept object's children come along, but the objects it only points at do not: after the load, a field that pointed at an object of the old scene holds a destroyed object, which compares equal to null.
public class GameSession : MonoBehaviour
{
public static GameSession Instance;
public int coins;
void Awake()
{
if (Instance != null)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
}
}This GameSession lives in the Menu scene. Play goes Menu, Level1, then back to the Menu, and the Menu builds all its objects again, a new GameSession included, while the kept one is still there. Without the check in Awake there would be two, and the newcomer would take over Instance with 0 coins. With it, the newcomer finds Instance already set, destroys itself and stops, and the session that came through the levels stays.
The return matters because Destroy waits until the end of the frame. Without it the rest of Awake still runs for the newcomer: Instance = this; would point every script at an object about to be destroyed.
Challenge
EasyA speedrun clock. The RunClock object in Level1 counts the seconds of the whole run and logs a split each time a level is finished. The gold Goal of Level1 loads Level2, whose goal loads Level1 again, and each goal calls RunClock.Instance.Split() first. Each level has its own HUD with a ClockText; the Inspector gives the RunClock the one in Level1. The arrows walk the Player. Change RunClock.cs so that:
- the clock keeps running through every scene load, without starting over;
- the time always shows in the
ClockTextof the level that is open, asTime: 12.3; - coming back to Level1, which holds a RunClock of its own, still leaves one clock, the one that has been running, and
RunClock.Instanceis that one.
Press Play, go to Level2 and back, and finish Level1 again, then Check.
Try it yourself
using UnityEngine;
using TMPro;
public class RunClock : MonoBehaviour
{
public static RunClock Instance;
public TMP_Text clockText;
private float seconds;
void Awake()
{
Instance = this;
}
void Update()
{
seconds += Time.deltaTime;
clockText.text = "Time: " + seconds.ToString("0.0");
}
public void Split()
{
Debug.Log("Split: " + seconds.ToString("0.0"));
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Building Real Games
2Buttons and Screens
Buttons and onClickLambdasWiring in the InspectorPanels On and OffHealth BarsRecap: Upgrade Shop5Saving with PlayerPrefs
Save a NumberLoad with a DefaultHigh ScoreSave SettingsRecap: Coins in the Bank3The Game Manager
One Script Runs the GameThe SingletonGame StatesSwitching on the StateRecap: Round Manager6Project: Endless Runner
Three LanesObstacles Ahead9The New Input System
Two Input SystemsKeyboard and MousePressed This FrameInput ActionsRecap: Input Swap