Keep Between Scenes
Part of the Building Real Games section of Coddy's Unity journey. Lesson 20 of 60.
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
EasyKeep one run clock going through every scene load.
- In
Awake(), ifInstance != null, callDestroy(gameObject);andreturn;. Otherwise setInstanceand callDontDestroyOnLoad(gameObject);. - A load destroys the old level's text, so in
Update(), before the text line, whenclockText == null, setclockText = GameObject.Find("ClockText").GetComponent<TMP_Text>();.
Press Play, go to Level2 and back: one clock keeps counting. 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"));
}
}
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 SwapPractice on your own: Unity playground