1
\$\begingroup\$

I need to get access to the variable flag loading from some script in another scene. The variable loading in my main menu scene and I need to access it in scripts in my game scene.

I'm not sure if using dontdestroyonload in this case is the right way and I don't want to make the loading variable public static either :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using UnityEditor;
using Cinemachine;
using UnityStandardAssets.Characters.ThirdPerson;

public class MenuController : MonoBehaviour
{
    #region Default Values
    [Header("Default Menu Values")]
    [SerializeField] private float defaultVolume;
    [SerializeField] private int defaultSen;
    [SerializeField] private bool defaultInvertY;

    [Header("Levels To Load")]
    public string _newGameButtonLevel;
    private string levelToLoad;

    public SceneFader sceneFader;
    public GameObject player;

    private int menuNumber;
    #endregion

    #region Menu Dialogs
    [Header("Main Menu Components")]
    [SerializeField] private GameObject menuDefaultCanvas;
    [SerializeField] private GameObject GeneralSettingsCanvas;
    [SerializeField] private GameObject graphicsMenu;
    [SerializeField] private GameObject soundMenu;
    [SerializeField] private GameObject controlsMenu;
    [SerializeField] private GameObject confirmationMenu;
    [Space(10)]
    [Header("Menu Popout Dialogs")]
    [SerializeField] private GameObject noSaveDialog;
    [SerializeField] private GameObject newGameDialog;
    [SerializeField] private GameObject loadGameDialog;
    #endregion

    #region Slider Linking
    [Header("Menu Sliders")]
    [SerializeField] private Text controllerSenText;
    [SerializeField] private Slider controllerSenSlider;
    public float controlSenFloat = 2f;
    [Space(10)]
    [SerializeField] private Text volumeText;
    [SerializeField] private Slider volumeSlider;
    [Space(10)]
    [SerializeField] private Toggle invertYToggle;
    #endregion

    public bool loading = false;

    #region Initialisation - Button Selection & Menu Order
    private void Start()
    {
        DontDestroyOnLoad(this);
        menuNumber = 1;
    }
    #endregion

    //MAIN SECTION
    public IEnumerator ConfirmationBox()
    {
        confirmationMenu.SetActive(true);
        yield return new WaitForSeconds(2);
        confirmationMenu.SetActive(false);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (menuNumber == 2 || menuNumber == 7 || menuNumber == 8)
            {
                GoBackToMainMenu();
                ClickSound();
            }

            else if (menuNumber == 3 || menuNumber == 4 || menuNumber == 5)
            {
                GoBackToOptionsMenu();
                ClickSound();
            }

            else if (menuNumber == 6) //CONTROLS MENU
            {
                ClickSound();
            }
        }
    }

    private void ClickSound()
    {
        GetComponent<AudioSource>().Play();
    }

    #region Menu Mouse Clicks
    public void MouseClick(string buttonType)
    {
        if (buttonType == "Controls")
        {
            controlsMenu.SetActive(true);
            menuNumber = 6;
        }

        if (buttonType == "Graphics")
        {
            GeneralSettingsCanvas.SetActive(false);
            graphicsMenu.SetActive(true);
            menuNumber = 3;
        }

        if (buttonType == "Sound")
        {
            GeneralSettingsCanvas.SetActive(false);
            soundMenu.SetActive(true);
            menuNumber = 4;
        }

        if (buttonType == "Exit")
        {
            Debug.Log("YES QUIT!");
            Application.Quit();
        }

        if (buttonType == "Options")
        {
            menuDefaultCanvas.SetActive(false);
            GeneralSettingsCanvas.SetActive(true);
            menuNumber = 2;
        }

        if (buttonType == "LoadGame")
        {
            menuDefaultCanvas.SetActive(false);
            loadGameDialog.SetActive(true);
            menuNumber = 8;
        }

        if (buttonType == "NewGame")
        {
            menuDefaultCanvas.SetActive(false);
            newGameDialog.SetActive(true);
            menuNumber = 7;
        }
    }
    #endregion

    public void VolumeSlider(float volume)
    {
        AudioListener.volume = volume;
        volumeText.text = volume.ToString("0.0");
    }

    public void VolumeApply()
    {
        PlayerPrefs.SetFloat("masterVolume", AudioListener.volume);
        Debug.Log(PlayerPrefs.GetFloat("masterVolume"));
        StartCoroutine(ConfirmationBox());
    }

    public void ControllerSen()
    {
        controllerSenText.text = controllerSenSlider.value.ToString("0");
        controlSenFloat = controllerSenSlider.value;
    }

    #region ResetButton
    public void ResetButton(string GraphicsMenu)
    {
        if (GraphicsMenu == "Audio")
        {
            AudioListener.volume = defaultVolume;
            volumeSlider.value = defaultVolume;
            volumeText.text = defaultVolume.ToString("0.0");
            VolumeApply();
        }

        if (GraphicsMenu == "Graphics")
        {
            controllerSenText.text = defaultSen.ToString("0");
            controllerSenSlider.value = defaultSen;
            controlSenFloat = defaultSen;

            invertYToggle.isOn = false;
        }
    }
    #endregion

    #region Dialog Options - This is where we load what has been saved in player prefs!
    public void ClickNewGameDialog(string ButtonType)
    {
        if (ButtonType == "Yes")
        {
            // Here to use a script to load the start game scene slowly smooth fade to black
            // Then fade back to transparent when loading/loaded the scene game !!!!!
            //SceneManager.LoadScene(_newGameButtonLevel);

            // When making new game to reset everything state scene everythig.
            // Including the uiSceneText for example.
            // To check how to reset everything to default !
            loading = false;
            newGameDialog.SetActive(false);
            StartCoroutine(sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, _newGameButtonLevel));
        }

        if (ButtonType == "No")
        {
            GoBackToMainMenu();
        }
    }

    public void ClickLoadGameDialog(string ButtonType)
    {
        if (ButtonType == "Yes")
        {
            //if (PlayerPrefs.HasKey("SavedLevel"))
            //{
            //Debug.Log("I WANT TO LOAD THE SAVED GAME");
            //LOAD LAST SAVED SCENE
            //levelToLoad = PlayerPrefs.GetString("SavedLevel");
            //SceneManager.LoadScene(levelToLoad);
            loading = true;
            newGameDialog.SetActive(false);
            StartCoroutine(sceneFader.FadeAndLoadScene(SceneFader.FadeDirection.In, _newGameButtonLevel));

            //}

            /*else
            {
                Debug.Log("Load Game Dialog");
                menuDefaultCanvas.SetActive(false);
                loadGameDialog.SetActive(false);
                noSaveDialog.SetActive(true);
            }*/
        }

        if (ButtonType == "No")
        {
            GoBackToMainMenu();
        }
    }
    #endregion

    #region Back to Menus
    public void GoBackToOptionsMenu()
    {
        GeneralSettingsCanvas.SetActive(true);
        graphicsMenu.SetActive(false);
        soundMenu.SetActive(false);

        VolumeApply();

        menuNumber = 2;
    }

    public void GoBackToMainMenu()
    {
        menuDefaultCanvas.SetActive(true);
        newGameDialog.SetActive(false);
        loadGameDialog.SetActive(false);
        noSaveDialog.SetActive(false);
        GeneralSettingsCanvas.SetActive(false);
        graphicsMenu.SetActive(false);
        soundMenu.SetActive(false);
        menuNumber = 1;
    }

    public void ClickQuitOptions()
    {
        GoBackToMainMenu();
    }

    public void ClickNoSaveDialog()
    {
        GoBackToMainMenu();
    }
    #endregion
}

At the top line 56 :

public bool loading = false;

Inside Start at line 61 :

DontDestroyOnLoad(this);

Then inside the method for starting a new game in line 207 :

loading = false;

And in the method that loading a saved game in line 228 :

loading = true;

Now that I know when it's starting a new game and when it's loading a game I want to use this loading variable in some scripts in my game scene.

For example this script :

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

public class SceneFader : MonoBehaviour
{
    #region FIELDS
    public GameObject fadeOutUIGameobjectImage;
    public float fadeSpeed = 0.8f;

    private MenuController menuController;
    private Image fadeOutUIImage;

    private void Start()
    {
        
    }

    public enum FadeDirection
    {
        In, //Alpha = 1
        Out // Alpha = 0
    }
    #endregion

    #region FADE
    public IEnumerator Fade(FadeDirection fadeDirection)
    {
        fadeOutUIGameobjectImage.SetActive(true);

        float alpha = (fadeDirection == FadeDirection.Out) ? 1 : 0;
        float fadeEndValue = (fadeDirection == FadeDirection.Out) ? 0 : 1;
        if (fadeDirection == FadeDirection.Out)
        {
            while (alpha >= fadeEndValue)
            {
                SetColorImage(ref alpha, fadeDirection);
                yield return null;
            }
            fadeOutUIGameobjectImage.SetActive(false);
        }
        else
        {
            fadeOutUIGameobjectImage.SetActive(true);
            while (alpha <= fadeEndValue)
            {
                SetColorImage(ref alpha, fadeDirection);
                yield return null;
            }
        }
    }
    #endregion

    #region HELPERS
    public IEnumerator FadeAndLoadScene(FadeDirection fadeDirection, string sceneToLoad)
    {
        yield return Fade(fadeDirection);
        SceneManager.LoadScene(sceneToLoad);

        SceneManager.sceneLoaded += SceneManager_sceneLoaded;
    }

    private void SceneManager_sceneLoaded(Scene arg0, LoadSceneMode arg1)
    {
        if (menuController.loading == true)
        {
            var saveLoad = GameObject.Find("Save System").GetComponent<SaveLoad>();
            saveLoad.Load();
        }
    }

    private void SetColorImage(ref float alpha, FadeDirection fadeDirection)
    {
        if(fadeOutUIImage == null)
        {
            fadeOutUIImage = fadeOutUIGameobjectImage.GetComponent<Image>();
        }

        fadeOutUIImage.color = new Color(fadeOutUIImage.color.r, fadeOutUIImage.color.g, fadeOutUIImage.color.b, alpha);
        alpha += Time.deltaTime * (1.0f / fadeSpeed) * ((fadeDirection == FadeDirection.Out) ? -1 : 1);
    }
    #endregion
}

At the top I did :

private MenuController menuController;

Then inside the event SceneManager_sceneLoaded I did at line 67 :

if (menuController.loading == true)

but I didn't make any reference to the MenuController script even if it's not destroyed. so loading will be null here I guess.

The idea is to use global in my project with the loading bool flag variable to find if the game is loading or if a new game started.

\$\endgroup\$
2
\$\begingroup\$

There are at least two ways. Either you can

  1. make singelton of your menucontroller, store static instance variable in script and access that way
  2. or find object from your scene

Singelton (something like this):

public static MenuController Instance { get; private set; }

public Awake() {
     if (Instance != null && Instance != this) 
     {
         Destroy(this.gameObject);
         return;
     }

     Instance = this;
     DontDestroyOnLoad( this.gameObject );
 }

And access it

 MenuController.Instance.CallSomeMethod();

Or find object: https://docs.unity3d.com/ScriptReference/GameObject.Find.html

Example from Unity page:

 // This returns the GameObject named Hand.
 hand = GameObject.Find("Hand");

Note that find object takes time, so do it once in Start().

\$\endgroup\$
2
  • \$\begingroup\$ Can you provide a short example what you mean with .Find() as well? Links tend to get broken. \$\endgroup\$
    – wondra
    Oct 18 '20 at 14:15
  • \$\begingroup\$ @wondra You call GameObject.Find("the name of the Game Object with DontDestroyOnLoad"); from the script you want to access it. It searches through the hierarchy for that Game Object and returns it if found. But it's pretty slow, so you don't want to search every frame; just do it once in Start() or Awake() and cache it in a global variable. Personally, though, I'd go for a singleton. \$\endgroup\$ Oct 19 '20 at 13:20

You must log in to answer this question.

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