static and Don't Destroy On load

Hello all ,

I am trying to make a static class that I could access from any other unity script in my game and I want it also to not destroy while moving from scene to scene.

The main idea is that I have a background music controller having functions such as :

public void SetAudioSrc()
    {
        AudioClip audio = BackgroundMusic[Random.Range(0, BackgroundMusic.Length)];
        audiosrc.PlayOneShot(audio);
    }

    public void SetMax()
    {
        audiosrc.volume = Max;
    }

    public void SetVolume(float Volume)
    {
        audiosrc.volume = Volume * Max;
    }

I want to be able to access these functions from any other script using :

BackgroudMusicController.Instance.SetVolume(0.4);

For example in my UI script I have (this will be called upon pressing save button after editing a slider for music volume):

public void SaveOptions()
    {
        Slider VolumeSlider = GameObject.Find("VolumeSlider").GetComponent<Slider>();
        if (VolumeSlider != null)
        {
            BackgroundMusicController.Instance.SetVolume(VolumeSlider.value);
        }

    }

However, destroying the BackgroundMusicController on each level will reset the music which is something I don’t want so that is why i added don’t destroy on load .
The full script is as follows now

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

public class BackgroundMusicController : MonoBehaviour {

    private static BackgroundMusicController _instance;

    public static BackgroundMusicController Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = GameObject.FindObjectOfType<BackgroundMusicController>();
                DontDestroyOnLoad(_instance);
            }

            return _instance;
        }

    }


    public AudioClip[] BackgroundMusic;
    public AudioSource audiosrc;
    public float Max;

    // Use this for initialization
    void Awake()
    {
        audiosrc = GetComponent<AudioSource>();
        SetAudioSrc();
        SetMax();


       
       
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void StartitUp()
    {
        return;
    }
    public void SetAudioSrc()
    {
        AudioClip audio = BackgroundMusic[Random.Range(0, BackgroundMusic.Length)];
        audiosrc.PlayOneShot(audio);
    }

    public void SetMax()
    {
        audiosrc.volume = Max;
    }

    public void SetVolume(float Volume)
    {
        audiosrc.volume = Volume * Max;
    }
    

}

I place the BackgroundMusic script on an empty gameobject on the MainMenu Scene

But the main issue is that now when I am going between scenes as follows :

  • MainMenu (working)
  • OptionMenu (working)
  • MainMenu (i have two of the gameobject : the one that is placed
    by default in the scene and the one
    that was kept with don’t destroy on
    load)

this is problem 1

and problem 2 is that I am obliged to call any function at least once in the BackgroundMuiscController from another script so that the dontdestroyonload works , otherwise it doesn’t work at all.

Please help
Have a good day :smiley:

There are a couple of approaches to avoiding the re-creation of multiple DontDestroyOnLoad objects. You could create a starting scene which is only passed through once (such as a start-up splash screen) where your dontDestroy objects are created. Or you could set your gameObject as a pre-fab, loading it into your scene only if it isn’t there already (from a previous instantiation). Or perhaps you could do it at script level to avoid the double-creation, in which case I think you would probably need to check for a previous instance in Awake(), and not re-create if another instance is found (not tested):

public class BackgroundMusicController : MonoBehaviour {
    
    public static BackgroundMusicController Instance;
    
    void Awake(){
        if (Instance!=null){
            GameObject.Destroy(Instance);
    } else {
        Instance = this;         
        DontDestroyOnLoad(this);
    }
}

Thank a lot but for put the object in a certain point of another scene? thanks again!