StartCoroutine by another class (Coroutine inside Coroutine - Instance class)

Hi, we have this class:

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

public class ScreenManager : MonoBehaviour {
	

	[SerializeField]
	private EFXManager m_blackScreenCover;

    [SerializeField]
    private EFXManager m_form;

    [SerializeField]
	private float m_minDuration = 1.5f;

    public static ScreenManager instance = null;

    void Awake()
    {
        if (instance == null)
            instance = this;

        else if (instance != this)
            Destroy(gameObject);

        DontDestroyOnLoad(gameObject);
    }

    void Update()
	{
        //if (Input.GetMouseButtonDown(0))
        //{
        //    StartCoroutine(LoadSceneAsyncScale("GameScreen"));
        //}
    }

    public IEnumerator LoadSceneAsyncScale(string sceneName)
    {
        // Scale IN
        yield return StartCoroutine(m_form.ScaleIn());

        // Load loading screen
        yield return SceneManager.LoadSceneAsync("LoadingScreen");

        // !!! unload old screen (automatic)

        // Fade to loading screen
        yield return StartCoroutine(m_blackScreenCover.FadeOut());

        float endTime = Time.time + m_minDuration;

        yield return SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);

        while (Time.time < endTime)
            yield return null;

        // Fade to black
        yield return StartCoroutine(m_blackScreenCover.FadeIn());

        // !!! unload loading screen
        LoadingSceneManager.UnloadLoadingScene();

        // Scale to new screen
        yield return StartCoroutine(m_form.ScaleOut());
    }

}

We are calling the method LoadSceneAsyncScale through another class. Everything seems to go well, but the method in question have more Coroutines ( yield return StartCoroutine (m_blackScreenCover.FadeOut (); for example ) and we noticed that it does not run. The implementation of the method will only LoadSceneAsyncScale to call yield return SceneManager.LoadSceneAsync ("LoadingScreen"); What could be going wrong? The call is incorrect?

My call:

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EventManager :  MonoBehaviour
{
    public void OnButtonClick()
    {
        StartCoroutine(ScreenManager.instance.LoadSceneAsyncScale("GameScreen")); //<< THIS IS A CALL, DON'T WORKS!
    }
}

But when we called directly from the class that has the method, in the Update () function could perform all routines:

public class ScreenManager : MonoBehaviour {
   //........
  void Update()
  {
    StartCoroutine(LoadSceneAsyncScale("GameScreen")); //<< THIS WORKS FINE!
  }
   //........
}

What are we doing wrong? Remembering that we are using the Singleton pattern.

Thanks a lot!

[SOLUTION]

With the help of the @Bunny83 response, we can implement the Singleton pattern in the class that will call the coroutine ( EventManager ) so the calling object will not be destroyed! Or just do what the @Bunny83 said in your answer!

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class EventManager : MonoBehaviour
{
   public static EventManager instance = null;

    void Awake()
    {
        if (instance == null)
            instance = this;

        else if (instance != this)
            Destroy(gameObject);

        DontDestroyOnLoad(gameObject);
    }

    public void OnButtonClick()
    {
        StartCoroutine(ScreenManager.instance.LoadSceneAsyncScale("GameScreen"));
    }
}

Thanks @Bunny83 :wink:

You run your outer coroutine on the “EventManager” script because you used the EventManager’s StartCoroutine method to start your coroutine. That will start the coroutine on the EventManager. If the EventManager is destroyed the coroutine will be gone. Try this

public void OnButtonClick()
{
    ScreenManager.instance.StartCoroutine(ScreenManager.instance.LoadSceneAsyncScale("GameScreen"));
}

This will make the coroutine to run on your singleton instance which will not be destroyed due to the DontDestroyOnLoad.

It’s usually a better approach to implement a normal wrapper method inside your ScreenManager which starts the Coroutine locally:

// inside SceneManager
public void StartLoadSceneAsyncScale(string sceneName)
{
    StartCoroutine(LoadSceneAsyncScale(sceneName));
}

And then use it like that:

//Inside EventManager
public void OnButtonClick()
{
    ScreenManager.instance.StartLoadSceneAsyncScale("GameScreen");
}