Overview
When developing games in Unity, you will inevitably encounter situations where you need certain objects to persist across scene transitions. For example, an AudioSource object that plays background music throughout the game, or a game manager that manages player scores and settings.
By default, when you load a new scene using SceneManager.LoadScene(), all GameObjects in the previous scene are automatically destroyed. This causes issues like background music cutting off or game state resetting every time you switch scenes.
To solve this problem and protect specific objects from scene transitions, Unity provides the Object.DontDestroyOnLoad() method. This article explains the basic usage and how to combine it with the Singleton pattern.
Basic Concept of DontDestroyOnLoad
DontDestroyOnLoad is a static method of the Object class. When you pass a GameObject to this method, that object moves to a special internal scene called the "DontDestroyOnLoad scene" and becomes immune to subsequent scene transitions.
The DontDestroyOnLoad scene is different from regular scenes in that it is not destroyed until the game ends. This makes it easy to manage objects that need to exist persistently throughout the game, such as background music players and game managers.
Code Example 1: Basic Usage
The simplest usage is to call DontDestroyOnLoad(this.gameObject) in the Awake() method of a script attached to the object you want to persist.
The following example is a script intended to be attached to an object that plays background music.
using UnityEngine;
public class BgmPlayer : MonoBehaviour
{
void Awake()
{
// Set this GameObject to not be destroyed on scene transitions
DontDestroyOnLoad(this.gameObject);
// Add BGM playback logic here
Debug.Log("BGM Player created and DontDestroyOnLoad applied.");
}
}
If a GameObject with this script is placed in a scene, it will persist through any number of scene transitions without being destroyed.
Common Pitfall for Beginners: Duplicate Object Creation
The most common mistake beginners make with DontDestroyOnLoad is duplicate object creation.
For example, suppose the BgmPlayer above is placed in Scene A, and the same BgmPlayer is also placed in Scene B. When you move from Scene A to Scene B:
DontDestroyOnLoadis applied to Scene A'sBgmPlayer, making it persistent.- When Scene B loads, a new
BgmPlayerfrom Scene B is created. - As a result, two
BgmPlayersexist in the game, causing issues like background music playing twice.
Code Example 2: Safe Management Using the Singleton Pattern
To solve this duplicate creation problem and ensure that only one instance of the persistent object exists in the game, DontDestroyOnLoad is commonly used in combination with the Singleton pattern.
The Singleton pattern is a design pattern that "guarantees only one instance of a class exists."
The following GameManager script is a practical example combining DontDestroyOnLoad with the Singleton pattern.
using UnityEngine;
public class GameManager : MonoBehaviour
{
// Static instance for external access
public static GameManager Instance { get; private set; }
void Awake()
{
// Check if an instance already exists
if (Instance != null && Instance != this)
{
// If one exists, destroy this newly created instance to prevent duplicates
Destroy(this.gameObject);
return;
}
// If no instance exists, set this as the Instance
Instance = this;
// Set to not be destroyed on scene transitions
DontDestroyOnLoad(this.gameObject);
Debug.Log("GameManager initialized and persisted.");
}
// Example: Game state management method accessible from anywhere
public void AddScore(int amount)
{
// Score addition logic
Debug.Log("Score increased by " + amount + " points.");
}
}
The key point of this code is that it checks for an existing instance in Awake() and immediately destroys itself if one already exists. This guarantees that only one GameManager exists no matter how many times scenes are loaded.
From other scripts, you can safely access this manager at any time using GameManager.Instance.AddScore(100);.
Summary
DontDestroyOnLoad is a powerful tool for managing persistent objects in Unity. Here are the key points covered in this article:
- Role of DontDestroyOnLoad: Used to keep specific GameObjects from being destroyed when scenes change. Suitable for persistent data management like background music and game managers.
- Basic Usage: Call
DontDestroyOnLoad(this.gameObject)in theAwake()method of a script attached to the object you want to persist. - Main Caution: Using
DontDestroyOnLoadalone can cause objects to be duplicated each time scenes change, leading to bugs. - Practical Solution: The most recommended approach is to combine
DontDestroyOnLoadwith the Singleton pattern to prevent object duplication and guarantee a single instance throughout the game. - Access Method: By making it a Singleton, you can safely and easily access the persistent object from anywhere in the game through
ClassName.Instance.
By applying this knowledge, scene management and object persistence in your Unity projects will become more refined. Enjoy your game development!