0
\$\begingroup\$

If the title wasn't clear enough (I don't really know how to explain it), basically I have an Audio Manager that is DontDestroyOnLoad. I also have a pause menu, that takes me back to the main menu, and in the main menu, I can reload the scene again. The problem is, upon reloading the scene, multiple copies of AudioManager is created in DontDestroyOnLoad, and I don't know how to solve it. My AudioManager script to give you a reference (only the important parts):

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

public class AudioManager : MonoBehaviour
{
    #region Instances
    private static AudioManager instance;
    public static AudioManager Instance
    {
        get
        {
            if (instance == null) //if instance doesn't exist, find an AudioManager
            {
                instance = FindObjectOfType<AudioManager>();

                if (instance == null) //if instance still doesn't exit, then it will create a new one
                {
                    instance = new GameObject("Spawned AudioManager", typeof(AudioManager)).GetComponent<AudioManager>();
                }
            }

            return instance;
        }
        private set
        {
            instance = value;
        }
    }
    #endregion

    #region Fields
    //the audio source can only play one looping sound at a time
    private AudioSource musicSource; 
    private AudioSource musicSource2; //purpose of having 2 musicSources is that we can use them to achieve effects like CrossFade
    private AudioSource sfxSource;

    private bool firstMusicSourceIsPlaying; 
    #endregion

    private void Awake()
    {
        //Make sure we don't destroy this instance
        DontDestroyOnLoad(this.gameObject); 

        //Create audio sources, and make them as references
        musicSource = this.gameObject.AddComponent<AudioSource>();
        musicSource2 = this.gameObject.AddComponent<AudioSource>();
        sfxSource = this.gameObject.AddComponent<AudioSource>();

        //loop musicSource
        musicSource.loop = true;
        musicSource2.loop = true;
    }

If you are reading this, thanks for taking your time and try to help me!

\$\endgroup\$
  • \$\begingroup\$ I'd suggest looking into the Singleton pattern for this particular case \$\endgroup\$ – Safa Jun 25 at 23:15
0
\$\begingroup\$

This is often handled by having the object check for an existing instance of itself in Awake, and self-destructing if one already exists:

private void Awake()
{
    // If there's already a copy of me, self-destruct and abort!
    if(instance != null && instance != this)
    {
        Destroy(gameObject);
        return;
    }
    /* // In your current code, the instance is populated via a static getter,
       // but you could instead choose to populate it here in Awake:
    else
    {
        instance = this;
    }
    */


    // Otherwise, keep me around forever and do my other Awake stuff...
    DontDestroyOnLoad(gameObject); 

    // ...other Awake stuff goes here...
}

Personally though, I like another approach:

  • Put your long-lived manager objects in a scene of their own.

  • Load that scene additively when they need to be created for the first time.

  • When you need to change/reset levels, unload the previous level scene and load the next, additively.

    This won't destroy or recreate the objects in your manager scene, which get to stay around unaffected the whole time, until you choose the right time to unload them.

This means no duplicate objects that need to fight for dominance, and no inefficiency of spawning copies only to destroy them.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.