Make music continue playing through scenes

Hi! I have an audio source attached to an object in my main menu scene, and i wanted it’s music to keep playing even when you are in SOME other scenes. For an example:

The main song is playing. The player is in the Main Menu scene and the music is at 1:43. The player clicks on Select Map and goes to the Map Selection scene. Then, the music continues from 1:43 until it finishes. As it has the loop, it plays again and again.

I don’t want the song to play in all the scenes, just some specific. Do someone know how to do this? I don’t have any idea of how to make this…

Let’s try this.

Create GameObject and assign any custom tag. For example, create tag “Music” and assign.
Attach script to this game object and make DontDestroyOnLoad:

using UnityEngine;

public class MusicClass : MonoBehaviour
{
    private AudioSource _audioSource;
    private void Awake()
    {
        DontDestroyOnLoad(transform.gameObject);
        _audioSource = GetComponent<AudioSource>();
    }

    public void PlayMusic()
    {
        if (_audioSource.isPlaying) return;
        _audioSource.Play();
    }

    public void StopMusic()
    {
        _audioSource.Stop();
    }
}

Attach your audio source to this object.

From scenes, where you want to play music, call method:

GameObject.FindGameObjectWithTag("Music").GetComponent<MusicClass>().PlayMusic();

From scenes, where you don’t want to play music, call method:

GameObject.FindGameObjectWithTag("Music").GetComponent<MusicClass>().StopMusic();

This works for me, latest version of unity: (C# code) (I also found this code somewhere on this forum :slight_smile:

using UnityEngine;
using System.Collections;

public class GameMusicPlayer : MonoBehaviour
{

    private static GameMusicPlayer instance = null;
    public static GameMusicPlayer Instance
    {
        get { return instance; }
    }
    void Awake()
    {
        if (instance != null && instance != this) {
            Destroy(this.gameObject);
            return;
        } else {
            instance = this;
        }
        DontDestroyOnLoad(this.gameObject);
    }
    // any other methods you need

}

First thread I found when looking for a solution to this problem, so I’ll add to this thread.

Here is a working solution that avoids the use of singletons, allowing you to add the script to multiple objects in the scene and tweak the behaviour via the inspector:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

/// <summary>
/// Attach this component to objects that you want to keep alive (e.g. theme songs) in certain scene transitions. 
/// For reusability, this component uses the scene names as strings to decide whether it survives or not after a scene is loaded 
/// </summary>
public class DontDestroyOnSelectedScenes : MonoBehaviour
{
    [Tooltip("Names of the scenes this object should stay alive in when transitioning into")]
    public List<string> sceneNames;

    [Tooltip("A unique string identifier for this object, must be shared across scenes to work correctly")]
    public string instanceName;

    // for singleton-like behaviour: we need the first object created to check for other objects and delete them in the scene during a transition
    // since Awake() callback preceded OnSceneLoaded(), place initialization code in Start()
    private void Start()
    {
        DontDestroyOnLoad(this.gameObject);

        // subscribe to the scene load callback
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        // delete any potential duplicates that might be in the scene already, keeping only this one 
        CheckForDuplicateInstances();

        // check if this object should be deleted based on the input scene names given 
        CheckIfSceneInList();
    }

    void CheckForDuplicateInstances()
    {
        // cache all objects containing this component
        DontDestroyOnSelectedScenes[] collection = FindObjectsOfType<DontDestroyOnSelectedScenes>();

        // iterate through the objects with this component, deleting those with matching identifiers
        foreach (DontDestroyOnSelectedScenes obj in collection)
        {
            if(obj != this) // avoid deleting the object running this check
            {
                if (obj.instanceName == instanceName)
                {
                    Debug.Log("Duplicate object in loaded scene, deleting now...");
                    DestroyImmediate(obj.gameObject);
                }
            }
        }
    }

    void CheckIfSceneInList()
    {
        // check what scene we are in and compare it to the list of strings 
        string currentScene = SceneManager.GetActiveScene().name;

        if (sceneNames.Contains(currentScene))
        {
            // keep the object alive 
        }
        else
        {
            // unsubscribe to the scene load callback
            SceneManager.sceneLoaded -= OnSceneLoaded;

            DestroyImmediate(this.gameObject);
        }
    }
}

Just add this script as if it were a component to the parent object (e.g. in the image, the empty game object carrying all the audio sources: “Audio”) and write down the name of the scenes it should survive in, then give it a unique string identifier relative to all other scripts in the scene using this component.

Have a look at this post:

This should work. Remember you can always save the Time Elapsed in a PlayerPrefs alternatively.

void Start () {
    DontDestroyOnLoad(this.gameObject);
}

Not tested yet but should work.

A Simpler way would be to set the GameObject with the audio souce to DontDestroy snd then in its Update check the scene its in and destroy if its the scene you dont want…

void Start()
{
if (SceneManager.GetActiveScene().name != “Racing”) {
DontDestroyOnLoad(gameObject);
}

}

// Update is called once per frame
void Update()
{
    if (SceneManager.GetActiveScene().name == "Racing") {
        Destroy(gameObject);
    }
}

Take it or leave it

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio; 

public class Misc : MonoBehaviour
{
    private void Awake()
    {
        Misc[] objects = FindObjectsOfType<Misc>();

        if (objects.Length > 1)
        {
            Destroy(objects[1].gameObject);
            return;
        }

        DontDestroyOnLoad(gameObject);
        
    }
}

I have a little of a different problem: I have three audio tracks playing at the same time (one drums, one melody and one some other rythm instruments) so that I can vary the music by changing their volumes separately.

The audio sources continue playing at the scene load, but they get out of sync. As a result the music is totally messed up. Any idea how I can keep them in sync? Short of stopping and restarting?