Music Player with and without the Singleton Pattern

I’ve got 3 scenes:
Start Menu
Game
Game Over

They are connected like we are doing in the lecture. I am trying to assign background music to them in the following manner:

Start Menu: BGM A
Game: BGM B
Game Over: BGM A

I want the Start Menu and Game Over scenes to be linked with the Singleton pattern so that the music will continue when I choose to play again but not when it enters the Game scene. The closest I’ve been able to manage to far is to have BGM A playing in every scene via the Singleton Pattern and BGM B playing over top of that during the Game scene and only during the Game scene.

Thanks,

Sandy

Can you post the code you have controlling this?

This is what I’m starting from.

Okay this is just one approach to the problem, it also assumes you will only have those three scenes:

Sorry if there’s errors, I typed all the code on my phone…

private void Update()
{
     if(!audioSource.isPlaying)
      {
              int index = SceneManager.GetActiveScene().buildIndex;
               if(index == 1)
               {
                      audioSource.clip = BGMB;
               }
               else
               {
                     audioSource.clip = BGMA;
                }
                audioSource.Play();
       }
}

Would that be instead of the SIngleton Pattern or including the Singleton?

That’s including your singleton pattern I was also assuming you knew how to deal with the audio.

Thank you, I got it to play but my SIngleton stopped working. I think I’m going to come back to this later but I appreciate the help!

That’s odd? Is this game object in every room? What does your new code look like? If you copy and paste it here maybe I can edit it.

Here is the code. Yes I have it added to each scene and have assigend the different music as part of the assignment.

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

public class MusicPlayer : MonoBehaviour
{
    AudioSource audioSource;
    [SerializeField] AudioClip menuMusic;
    [SerializeField] AudioClip gameMusic;

    private void Start()
    {
        audioSource = GetComponent<AudioSource>();    
    }

    void Awake()
    {
        //SetUpSingleton();
    }

    private void SetUpSingleton()
    {
        // this will find its own type allowing for generic singleton

        if (FindObjectsOfType(GetType()).Length > 1)
        {
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }
    }

    // Update is called once per frame
    private void Update()
    {
        if (!audioSource.isPlaying)
        {
            int index = SceneManager.GetActiveScene().buildIndex;
            if (index == 1)
            {
                audioSource.clip = gameMusic;
            }
            else
            {
                audioSource.clip = menuMusic;
            }
            audioSource.Play();
        }
    }
}

I noticed you commented out your call to set up your singleton

Yes, sorry. I had done that while playing with it to try to get it to work. As it is with the Singleton being called then it will start a SIngleton pattern on my menuMusic and not play the GameMusic. Not calling the singleton gives me the correct music during each scene but it restarts when switching from the Game Over scene to the Start scene.

It will have to be a singleton to persist.

I have a similar issue and could not fix it.

I have four scenes, each with a music playing:

StartMenu - Music A

Game - Music B

GameOver - Music C

Credits - Music C

From the GameOver to Credits the Music should keep on playing using the Singleton Pattern. When changing from GameOver or Credits to the Game or StartMenu scenes, the Music C should stop, but that is not happening.

I have tried the solution on this topic https://community.gamedev.tv/t/excluding-1-level-from-our-singleton/125341/2, but that did not work out for me.

I want to learn how to make this work for the knowledge itself, I don’t plan on making this project big at the moment.

My code is the same as Rick though on the lesson:

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

public class GameOverCreditsMusicPlayer : MonoBehaviour
{
    void Awake()
    {
        SetUpSingleton();
        Debug.Log(SceneManager.GetActiveScene().name);
    }

    private void SetUpSingleton()
    {
        if (FindObjectsOfType(GetType()).Length > 1)
        {
            Destroy(gameObject);
        }
        else
        {
             DontDestroyOnLoad(gameObject);
        }
    }
}

I believe the problem is the Class that I am using (GameOverCreditsMusicPlayer) only exists in the GameOver and Credits Scripts, and when the game transitions to either MainMenu or Game the Class being used has a different name and the if statement stop making sense.

Hi @Silk_90,
I’m having a similar issue. Like you, I have different music for different scenes. I’d also quite like the music to stop when the player dies. So I’d be keen to know how you got on.

Moving from Start (Music A) to Main Game (Music B) works fine with the approach Rick gave us. But I am struggling to:

  1. stop the music when the player dies.

I’ve tried serializing the MusicPlayer in the player.cs script, and then destroy(musicPlayer) the object, but this doesn’t work because, as a result of the singleton process, musicPlayer becomes a DontDestroyonLoad object…

  1. move back to Music A on the Start Menu, from the Game Over screen.

How did you get on, bud? Have you had any luck?

Could it be as simple as merely not having a Singleton pattern?

Hey, @AJMeyer. I managed to fix whatever issues I had by doing some other tutorials. Here’s my code:

public class MusicPlayer : MonoBehaviour
{
    [Header("Music Selection")]
    [SerializeField] AudioClip menuSong;
    [SerializeField] AudioClip[] backgroundSongs;
    [SerializeField] AudioClip gameOverSong;
    [SerializeField] AudioClip victorySong;
    //[SerializeField] [Range(0, 1)] float musicVolume;

    // Cached References

    private AudioSource audioSource;
    private MusicPlayer[] musicPlayer;
    private int randomSongIndex;

    private void Awake()
    {
        audioSource = GetComponent<AudioSource>();
        musicPlayer = FindObjectsOfType<MusicPlayer>();
        SetUpSingleton();
    }

    private void SetUpSingleton()
    {
        if (musicPlayer.Length > 1)
        {
            gameObject.SetActive(false);
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }
    }

    private void OnEnable()
    {
        SceneManager.sceneLoaded += OnSceneLoaded;
    }

    void OnSceneLoaded(Scene scene, LoadSceneMode mode)
    {
        CheckAndChangeMusic();
    }

    private void OnDisable()
    {
        SceneManager.sceneLoaded -= OnSceneLoaded;
    }

    private void CheckAndChangeMusic()
    {
        if (SceneManager.GetActiveScene().buildIndex == 0)
        {
            audioSource.clip = menuSong;
            audioSource.loop = false;
        }
        if (SceneManager.GetActiveScene().buildIndex == 1)
        {
            return;
        }
        else if (SceneManager.GetActiveScene().name == "GameScene")
        {
            randomSongIndex = Random.Range(0, backgroundSongs.Length);
            audioSource.clip = backgroundSongs[randomSongIndex];
            audioSource.loop = true;
        }
        audioSource.Play();
    }

    public void PlayGameOverClip()
    {
        audioSource.clip = gameOverSong;
        audioSource.loop = false;
        audioSource.Play();
    }

    public void PlayVictoryClip()
    {
        audioSource.clip = victorySong;
        audioSource.loop = false;
        audioSource.Play();
    }
}

In this particular project I had a Menu Scene (Index 0) with its own music, a Credits Scene (Index 1) with no sounds and then a Game Scene (Index 2) that could play from an array of 4 different musics, chosen at random. If the player dies or finish the game, a different audio is played to characterize the moment. The Victory and Game Over are called as UI and not as Scenes. They are Canvas that are turned On when needed. The Music Player still exists using the Singleton pattern.

Let me know if you could make it work. Sorry for the delay.