0
\$\begingroup\$

I have two scenes: "Main Menu" and "Game."

When running the game it starts with the Main Menu scene loaded. Then, when starting a new game the Main Menu scene is unloaded and the Game scene is loaded. However, even if the Game scene is loaded it keeps showing the Main Menu scene in the name:

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

public class AudioManager : MonoBehaviour
{
    public GameObject gameAudio;

    private AudioSource audioSource;
    private string sceneName;
    private bool currentScene = false;

    void Awake()
    {
        DontDestroyOnLoad(transform.gameObject);
    }

    // Start is called before the first frame update
    void Start()
    {
        // Create a temporary reference to the current scene.
        Scene currentScene = SceneManager.GetActiveScene();

        // Retrieve the name of this scene.
        sceneName = currentScene.name;

        audioSource = gameAudio.GetComponent<AudioSource>();

        var mainmenumusic = GameObject.Find("Main Menu Settings");
        audioSource.volume = mainmenumusic.GetComponent<AudioSource>().volume;
    }

    // Update is called once per frame
    void Update()
    {
        if (sceneName == "Game" && currentScene == false)
        {
            audioSource.Play();
            currentScene = true;
        }
        else
        {
            if (sceneName != "Game")
            {
                audioSource.Stop();
                currentScene = false;
            }
        }
    }

    //Called when Slider is moved
    public void changeVolume(float sliderValue)
    {
        audioSource = gameAudio.GetComponent<AudioSource>();
        audioSource.volume = sliderValue;
    }
}

During Update, even if the Game scene has loaded (and only the Game scene is loaded) sceneName is still set to "Main Menu":

if (sceneName == "Game" && currentScene == false)

sceneName is never "Game."

And a side question:

When I press the escape key back to the main menu it keeps creating the DontDestroyOnLoad object over and over again. How can I avoid creating the DontDestroyOnLoad all the time? This script is in my Game scene:

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class BackToMainMenu : MonoBehaviour
{
    public GameObject[] objsToDisable;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (Time.timeScale == 0)
            {
                DisableEnableUiTexts(true);
                SceneManager.UnloadSceneAsync(0);
                Cursor.visible = false;
                Time.timeScale = 1;
            }
            else
            {
                Time.timeScale = 0;
                MenuController.LoadSceneForSavedGame = false;
                SceneManager.LoadScene(0, LoadSceneMode.Additive);
                SceneManager.sceneLoaded += SceneManager_sceneLoaded;

                Cursor.visible = true;
            }
        }
    }

    private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        DisableEnableUiTexts(false);
    }

    private void DisableEnableUiTexts(bool enabled)
    {
        foreach (GameObject go in objsToDisable)
        {
            if (go.name == "Cameras")
            {
                foreach(Transform child in go.transform)
                {
                    if(child.name == "Main Camera")
                    {
                        if (enabled == false)
                        {
                            child.GetComponent<Camera>().enabled = false;
                        }
                        else
                        {
                            child.GetComponent<Camera>().enabled = true;
                        }
                    }
                }
            }
            else
            {
                go.SetActive(enabled);
            }
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Can you boil this down to a minimal example that demonstrates your problem? It looks like you have quite a lot of code here unrelated to loading a scene and checking its name. \$\endgroup\$
    – DMGregory
    Commented Jan 19, 2021 at 10:36

2 Answers 2

1
\$\begingroup\$

The reason for this behavior is that you are loading your scenes with LoadSceneMode.Additive. This parameter allows you to have more than one scene at the same time. So the concept of "active scene" becomes a bit fuzzy.

What happens in this situation is that the currently "active scene" stays the "active scene", and the content of the new scene gets added as another scene which is also being executed. However, you can make that new scene the active scene with SceneManager.SetActiveScene. Or if you don't actually want to keep the main menu scene, then you can avoid all that and use LoadSceneMode.Single. That will unload the old scene, load the new scene and set the new scene to the active scene.

But what does the "active scene" actually mean? The documentation says:

The currently active Scene is the Scene which will be used as the target for new GameObjects instantiated by scripts.

What you are apparently trying to do here is to use the "active scene" as a proxy for what state your game is currently in. This might not be the best idea, especially if combined with additive scene loading. When you want your game to behave differently depending on the current state it is in, then you might want to implement a proper state-handling mechanism. But when you just want your audio manager to behave differently in the main menu and in the game, then perhaps you don't need one audio manager with DontDestroyOnLoad. Perhaps what you might need are two audio managers with each one being a part of their respective scene.

\$\endgroup\$
0
\$\begingroup\$

To answer your side question first, You are trying to create a persistent class and for that what you can do is:

using UnityEngine;

public class UnitySingletonPersistent<T> : MonoBehaviour where T : Component
    {
        private static T instance;

        public static T Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = FindObjectOfType<T>();
                    if (instance == null)
                    {
                        var obj = new GameObject {hideFlags = HideFlags.HideAndDontSave};
                        instance = obj.AddComponent<T>();
                    }
                }

                return instance;
            }
        }

        public virtual void Awake()
        {
            DontDestroyOnLoad(gameObject);
            if (instance == null)
            {
                instance = this as T;
            }
            else
            {
                Destroy(gameObject);
            }
        }
    }

Now inherit from this like:

public class AudioManager : UnitySingletonPersistent<AudioManager>
{
   //Remove awake from here you don't need Don't Destroy On Load here.
}

Now towards your main question. The problem is that you are getting SceneManager.GetActiveScene() in the Start() which is why when in Update when even scene changes you don't have updated scene name.

Try Checking name like:

if (SceneManager.GetActiveScene().name == "Game" && currentScene == false)
{
   //Your rest of the code
}

OR you could update your currentScene variable every time you change the scene instead of doing that only once.

public void Start()
    {
        SceneManager.activeSceneChanged += ChangedActiveScene;
    }

private void ChangedActiveScene(Scene current, Scene next)
    {
        string currentName = current.name;

        if (currentName == null)
        {
            // Scene1 has been removed
            currentName = "Replaced";
        }

        Debug.Log("Scenes: " + currentName + ", " + next.name);
    }
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .