Handling Scene Management, function not visible

Hi, I’ve followed this video

to create a Scene Manager.
I created a Canvas prefab which makes the transitions between scenes and I added it in my main menu scene (which has another canvas that handles the menu) and I’ve attached to it the next script:

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

public class SceneController : MonoBehaviour {

    public static SceneController MyInstance;
    //It's a static instance thnt won't be destroyed over scenes

    public float TransitionTimeDelay=0.1f;
    public string TargetScene;
    CanvasGroup MyCanvasGroup;

    bool IsAddictive;

    // Use this for initialization
    void Awake () {

        //Check if we have duplicated instances of the same class and in case we do, delete one
        if (MyInstance == null) {
            MyInstance = this;
            DontDestroyOnLoad (gameObject);                            //The gameObject is the Canvas
            MyCanvasGroup=GetComponent<CanvasGroup>();
        } else
            Destroy (gameObject);


    }
   
    // Update is called once per frame
    void Update () {
        //That's only for test
        if (Input.GetKey (KeyCode.Q))
            SetTargetScene ("Scena", false);
    }



    public void SetTargetScene(string SceneToLoad, bool Addictive)
    {
        //If we're pointing to the same scene, quit the function
        if (SceneManager.GetActiveScene ().name == SceneToLoad)
            return;
        TargetScene = SceneToLoad;
        IsAddictive = Addictive;

        StopCoroutine ("TransitionWithFade");
        StartCoroutine ("TransitionWithFade", 1);

        //Set the target alpha to 1, so to be completely opaque
    }

    //Coroutine that operates while loading the next scene
    IEnumerator TransitionWithFade(float targetAlpha)
    {
        float AlphaDifference = Mathf.Abs (MyCanvasGroup.alpha - targetAlpha);
        float TransitionRate = 0;

        while (AlphaDifference > 0.045f) {
            //Smoothen the transition between the two scenes.
            //Syntaxis: current alpha ! target alpha | current velocity | transition time
            MyCanvasGroup.alpha = Mathf.SmoothDamp (MyCanvasGroup.alpha, targetAlpha, ref TransitionRate, TransitionRate);
            AlphaDifference = MyCanvasGroup.alpha - targetAlpha;                    //Update Alpha difference between scenes/image

            yield return null;              //Interrups coroutine
        }

        MyCanvasGroup.alpha = targetAlpha;

        //When MyCanvasGroup.alpha is 1 (fully opaque), it means we have to move to the next scene, so we need to call the actual method doing that.
        if (targetAlpha == 1) {
            StartCoroutine ("LoadScene");
        }
    }

    IEnumerator LoadScene()
    {
        if(IsAddictive==false)
            SceneManager.LoadScene (TargetScene);                            //Load the correct scene
        else
            SceneManager.LoadScene (TargetScene, LoadSceneMode.Additive);
       
        string ActiveScene=SceneManager.GetActiveScene().name;            //Refresh the current scene

        //If the scene is not loaded yet, so it means our current scene is not the target scene (because of slow PC performance, troubles etc...)
        //Continue with the coroutine until the desired scene is completely loaded
        while (ActiveScene != TargetScene) {
            ActiveScene = SceneManager.GetActiveScene ().name;
            yield return null;
        }

        StartCoroutine ("TransitionWithFade", 0);            //When the scene is loaded, turn the canvas group alpha to be 0

    }
}

I have some scenes in my assets and I will create new ones.
Unfortunately in the main scene where I have a “Play” button, if I add an OnClick event, I drag the canvas element that handles the scene management, I cannot see my “SetTargetScene method” even if it is public.

So I cannot set what scene to upload when pressing the button.
What can I do?

Thank you for any help

I could be wrong, but I think those events only accept 0 or 1 arguments by default.
So, you could setup intermediate methods to handle that (like 2 make ).
Or you could shorten the method parameter list , if you don’t need the second argument.
or something else along those lines…

I created another Canvas and edited the code as it follows:

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

public class SceneController : MonoBehaviour {

    public static SceneController MyInstance;
    //It's a static instance thnt won't be destroyed over scenes

    public float TransitionTimeDelay=0.1f;
    public string TargetScene;
    CanvasGroup MyCanvasGroup;

    int IsAddictive=0;

    // Use this for initialization
    void Awake () {

        //Check if we have duplicated instances of the same class and in case we do, delete one
        if (MyInstance == null) {
            MyInstance = this;
            DontDestroyOnLoad (gameObject);                            //The gameObject is the Canvas
            MyCanvasGroup=GetComponent<CanvasGroup>();
        } else
            Destroy (gameObject);


    }
   
    // Update is called once per frame
    void Update () {
        //That's only for test
        if (Input.GetKey (KeyCode.Q))
            SetTargetScene ("Scena", 0);
    }



    public void SetTargetScene(string SceneToLoad, int Addictive)
    {
        //If we're pointing to the same scene, quit the function
        if (SceneManager.GetActiveScene ().name == SceneToLoad)
            return;
        TargetScene = SceneToLoad;
        IsAddictive = Addictive;

        StopCoroutine ("TransitionWithFade");
        StartCoroutine ("TransitionWithFade", 1);

        //Set the target alpha to 1, so to be completely opaque
    }

    //Coroutine that operates while loading the next scene
    IEnumerator TransitionWithFade(float targetAlpha)
    {
        float AlphaDifference = Mathf.Abs (MyCanvasGroup.alpha - targetAlpha);
        float TransitionRate = 0;

        while (AlphaDifference > 0.045f) {
            //Smoothen the transition between the two scenes.
            //Syntaxis: current alpha ! target alpha | current velocity | transition time
            MyCanvasGroup.alpha = Mathf.SmoothDamp (MyCanvasGroup.alpha, targetAlpha, ref TransitionRate, TransitionRate);
            AlphaDifference = MyCanvasGroup.alpha - targetAlpha;                    //Update Alpha difference between scenes/image

            yield return null;              //Interrups coroutine
        }

        MyCanvasGroup.alpha = targetAlpha;

        //When MyCanvasGroup.alpha is 1 (fully opaque), it means we have to move to the next scene, so we need to call the actual method doing that.
        if (targetAlpha == 1) {
            StartCoroutine ("LoadScene");
        }
    }

    IEnumerator LoadScene()
    {
        if(IsAddictive==0)
            SceneManager.LoadScene (TargetScene);                            //Load the correct scene
        else
            SceneManager.LoadScene (TargetScene, LoadSceneMode.Additive);
       
        string ActiveScene=SceneManager.GetActiveScene().name;            //Refresh the current scene

        //If the scene is not loaded yet, so it means our current scene is not the target scene (because of slow PC performance, troubles etc...)
        //Continue with the coroutine until the desired scene is completely loaded
        while (ActiveScene != TargetScene) {
            ActiveScene = SceneManager.GetActiveScene ().name;
            yield return null;
        }

        StartCoroutine ("TransitionWithFade", 0);            //When the scene is loaded, turn the canvas group alpha to be 0
    }

}

If I press the Q button the scene changes, but I cannot still see SetTargetScene in Button—>OnClick event

Right, well that makes sense because you didn’t make a new method. You kinda chose a slghtly different path.
What I was meaning was this:

public void SetMyScene(string SceneToLoad) {
   SetTargetScene(SceneToLoad, 0);
}

Something like that , I think then you could see the variable in the inspector

1 Like

Hi, I’m having another trouble with this script. I decided not to create a new thread because I think it’s not relevant.

My new SceneController.cs is as follows:

public class SceneController : MonoBehaviour {



    public float TransitionTimeDelay=0.1f;
    string TargetScene;
    CanvasGroup MyCanvasGroup;

    int IsAddictive=0;

    public string WhichButton = "";

    public GameObject Resume;


    public static SceneController MyInstance;
    //It's a static instance thnt won't be destroyed over scenes
    // Use this for initialization
    void Awake () {

        //Check if we have duplicated instances of the same class and in case we do, delete one
        if (MyInstance == null) {
            MyInstance = this;
            DontDestroyOnLoad (gameObject);                            //The gameObject is the Canvas
            MyCanvasGroup=GetComponent<CanvasGroup>();
        } else
            Destroy (gameObject);

        if (MyInstance.WhichButton.CompareTo ("Play") == 0 || MyInstance.WhichButton.CompareTo ("Resume") == 0)
            Resume.SetActive (true);
    }

    public void SetTargetScene(string SceneToLoad, int Addictive)
    {
        //If we're pointing to the same scene, quit the function
        if (SceneManager.GetActiveScene ().name == SceneToLoad)
            return;
        TargetScene = SceneToLoad;
        IsAddictive = Addictive;

        StopCoroutine ("TransitionWithFade");
        StartCoroutine ("TransitionWithFade", 1);

        //Set the target alpha to 1, so to be completely opaque
    }

    //Coroutine that operates while loading the next scene
    IEnumerator TransitionWithFade(float targetAlpha)
    {

        yield return new WaitForSeconds(2);

        float AlphaDifference = Mathf.Abs (MyCanvasGroup.alpha - targetAlpha);
        float TransitionRate = 0f;

        while (AlphaDifference > 0.025f) {
            //Smoothen the transition between the two scenes.
            //Syntaxis: current alpha ! target alpha | current velocity | transition time
            MyCanvasGroup.alpha = Mathf.SmoothDamp (MyCanvasGroup.alpha, targetAlpha, ref TransitionRate, TransitionTimeDelay);
            AlphaDifference = MyCanvasGroup.alpha - targetAlpha;                    //Update Alpha difference between scenes/image

            yield return null;              //Interrups coroutine
        }

        MyCanvasGroup.alpha = targetAlpha;

        //When MyCanvasGroup.alpha is 1 (fully opaque), it means we have to move to the next scene, so we need to call the actual method doing that.
        if (targetAlpha == 1) {
            StartCoroutine ("LoadScene");
        }
    }

    IEnumerator LoadScene()
    {
        if(IsAddictive==0)
            SceneManager.LoadScene (TargetScene);                            //Load the correct scene
        else
            SceneManager.LoadScene (TargetScene, LoadSceneMode.Additive);
       
        string ActiveScene=SceneManager.GetActiveScene().name;            //Refresh the current scene

        //If the scene is not loaded yet, so it means our current scene is not the target scene (because of slow PC performance, troubles etc...)
        //Continue with the coroutine until the desired scene is completely loaded
        while (ActiveScene != TargetScene) {
            ActiveScene = SceneManager.GetActiveScene ().name;
            yield return null;
        }

        StartCoroutine ("TransitionWithFade", 0);            //When the scene is loaded, turn the canvas group alpha to be 0
    }

    public void MyMethod()
    {
        //GameObject.Find ("Play").GetComponent<Animator> ().SetTrigger ("Pressed");
        Vector3 temp=new Vector3(0.0f,0.0f,-2f);
        this.transform.position = temp;

        SetTargetScene ("Scena", 0);
    }

    public void ChangeScenesWithButton(string whatScene)
    {       
        SetTargetScene (whatScene, 0);
    }

    public void SetButtonPressed(string PlayorResume)
    {
        //Sets a variable that stores data wether I pressed Play or Resume button.
        WhichButton=PlayorResume;
    }
}

I have added a SetButtonPressed method that sets me the name of the button pressed. It can be either “Play” or “Resume”.

I don’t know if I’d said that in the original post, but SceneManager is an empty object on which SceneController.cs is attached.
SceneManager is undestroyable and I created it in my Menu scene the first time.

My scene sequence is: Intro<Menu(where I created SceneManager)<Loading<MainGame.

In MainGame scene I have a script attached to the player that saves his last position.
That script contains:

    void Start()
    {
        if (SceneController.MyInstance.WhichButton.CompareTo("Resume")==0)        //If the game was temporary suspended, load last saved position
            RetreiveData ();
        else
            MyTransform.position = new Vector3 (34.88506f, 0.908f, 91.97422f);    //Otherwise position the player in front of the main access
    }

Another script that handles the player’s healthbar contains:

    void Start()
    {
        animator = GetComponent<Animator>(); // Determination the animator
        width = ContentLine.rect.width; // Define the object width "Content"

        if (SceneController.MyInstance.WhichButton.CompareTo("Resume")==0) {
            currentHp = PlayerPrefs.GetFloat ("Health", 100f);
        } else
            currentHp = 0f;
    }

The RecordLastPos script and the latter both give me the following NullException: “Object reference not set to an instance of an object”.

I have taken many ways attempting to solve it but with no result.
Could you have any idea of what it can be?

Thanks

Is the null reference on the MyInstance you mean?

No, in the if statements of the last two scripts