- Home /
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 ;)
$$anonymous$$aybe try it without the yield return before it, or have a line with yield return null line before starting each Coroutine.
Well, too bad :(
A workaorund would be to make the CR call seperate (normal) functions that in turn start the respective CoRoutines.
Answer by Bunny83 · Jul 24, 2016 at 05:32 PM
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");
}
Thank you very much for your reply @Bunny83! It really works very well ... I did not know that a coroutine was destroyed along with the object. All you also said works by implementing Singleton in Event$$anonymous$$anager. :) I update the question with solution!