1

I have a game with four scenes, a menu scene, a loading scene, and two game scenes. All is well, when I am transitioning from my menu scene to my game scenes, but whenever I transition from my game scenes back to my menu scene or reload the game scene, the loading scene simply stops responding. I get a warning message that says "NetworkManager detected a script reload in the editor. This has caused the network to be shut down" only when I try to reload the currently active game scene. This issue is also present when I play in the build! I used print statements to trace down where my code stopped running, and I figured out that it was the Yield Return New WaitForSeconds() which caused the game to freeze. Why is that?

I have two scripts that controls transitioning. One simple script called on UIButtons for telling the second more complex script called in the preload scene to load the scene it's supposed to load and create animations. I have made sure that I was loading on to the correct scene, and that all of the scenes were added into my build settings.

The following pictures show the loading scene not responding. The first picture shows what happens when I try to reload the current game scene, and the second picture shows what happens when I try to load the menu scene:

Loading Screen Freezing when I try to reload the game scene

Loading Screen Freezing when I try to load the menu scene

My Loading Scene Script:

public class LoadingScreenManager : MonoBehaviour {

[Header("Loading Visuals")]
public Image loadingIcon;
public Image loadingDoneIcon;
public Text loadingText;
public Image progressBar;
public Image fadeOverlay;

[Header("Timing Settings")]
public float waitOnLoadEnd = 0.25f;
public float fadeDuration = 0.25f;

[Header("Loading Settings")]
public LoadSceneMode loadSceneMode = LoadSceneMode.Single;
public ThreadPriority loadThreadPriority;

[Header("Other")]
// If loading additive, link to the cameras audio listener, to avoid multiple active audio listeners
public AudioListener audioListener;

AsyncOperation operation;
Scene currentScene;

public static int sceneToLoad = -1;
// IMPORTANT! This is the build index of your loading scene. You need to change this to match your actual scene index
static int loadingSceneIndex = 1;

public static void LoadScene(int levelNum) {                
    Application.backgroundLoadingPriority = ThreadPriority.High;
    sceneToLoad = levelNum;
    SceneManager.LoadScene(loadingSceneIndex);
}

void Start() {
    if (sceneToLoad < 0)
        return;

    fadeOverlay.gameObject.SetActive(true); // Making sure it's on so that we can crossfade Alpha
    currentScene = SceneManager.GetActiveScene();
    StartCoroutine(LoadAsync(sceneToLoad));
}

private IEnumerator LoadAsync(int levelNum) {
    ShowLoadingVisuals();

    yield return null; 

    FadeIn();
    StartOperation(levelNum);

    float lastProgress = 0f;

    // operation does not auto-activate scene, so it's stuck at 0.9
    while (DoneLoading() == false) {
        yield return null;

        if (Mathf.Approximately(operation.progress, lastProgress) == false) {
            progressBar.fillAmount = operation.progress;
            lastProgress = operation.progress;
        }
    }

    if (loadSceneMode == LoadSceneMode.Additive)
        audioListener.enabled = false;

    ShowCompletionVisuals();
  //THE PRINT STATEMENT WORKS FINE RIGHT HERE! The value of waitOnLoadEnd is only 1
    yield return new WaitForSeconds(waitOnLoadEnd);
 //THE PRINT STATEMENT STOPS RUNNING RIGHT HERE!  
    FadeOut();

    yield return new WaitForSeconds(fadeDuration);

    if (loadSceneMode == LoadSceneMode.Additive)
        SceneManager.UnloadScene(currentScene.name);
    else
        operation.allowSceneActivation = true;
}

private void StartOperation(int levelNum) {
    Application.backgroundLoadingPriority = loadThreadPriority;
    operation = SceneManager.LoadSceneAsync(levelNum, loadSceneMode);


    if (loadSceneMode == LoadSceneMode.Single)
        operation.allowSceneActivation = false;
}

private bool DoneLoading() {
    return (loadSceneMode == LoadSceneMode.Additive && operation.isDone) || (loadSceneMode == LoadSceneMode.Single && operation.progress >= 0.9f); 
}

void FadeIn() {
    fadeOverlay.CrossFadeAlpha(0, fadeDuration, true);
}

void FadeOut() {
    fadeOverlay.CrossFadeAlpha(1, fadeDuration, true);
}

void ShowLoadingVisuals() {
    loadingIcon.gameObject.SetActive(true);
    loadingDoneIcon.gameObject.SetActive(false);

    progressBar.fillAmount = 0f;
    loadingText.text = "LOADING...";
}

void ShowCompletionVisuals() {
    loadingIcon.gameObject.SetActive(false);
    loadingDoneIcon.gameObject.SetActive(true);

    progressBar.fillAmount = 1f;
    loadingText.text = "LOADING DONE";
}

}

Script on UIButtons that call the above script:

 public class LoadingSceneButton : MonoBehaviour {

public void LoadSceneWithLoadingScreen(int sceneNumber){
    if (sceneNumber < 0 || sceneNumber >= SceneManager.sceneCountInBuildSettings) {
        Debug.LogWarning ("Can't Load Scene, because It Doesn't Exist!");
    }

    LoadingScreenManager.LoadScene (sceneNumber);
}
}
Aaron Ge
  • 258
  • 3
  • 21
  • hey Aaron! I did further tidy up this answer ... http://stackoverflow.com/a/35891919/294884 I have tried to explain the process more clearly. Maybe it will help? – Fattie Jul 30 '16 at 18:37

1 Answers1

1

(1) Don't use "print", please use this:

  Debug.Log("fadeDuration is ....... " , fadeDuration.ToString("f4");

add that line of code just before you call FadeOut and also please add it inside FadeOut


(2) problems with CrossFadeAlpha

Please note that CrossFadeAlpha is extremely difficult to use! It's a real pain! It only works on UnityEngine.UI.Graphic, and it's tricky when used with coroutines.

public static void FadeOut(this Graphic g)
    {
    g.GetComponent<CanvasRenderer>().SetAlpha(1f);
    g.CrossFadeAlpha(0f,.15f,false);
    }

(3) problems with loading a scene in Unity5 !!!

Yes there is a

known issue

where it gets stuck on 0.9. Maybe this is the main problem at hand.

check out ... http://answers.unity3d.com/answers/1146173/view.html

and ... http://answers.unity3d.com/answers/1073667/view.html

Some basic working code example....

public void LaunchSoundboard()
    {
    StartCoroutine(_soundboard());
    }
private IEnumerator _soundboard()
    {
    Grid.music.Duck();

    yield return new WaitForSeconds(.2f);

    AsyncOperation ao;
    ao = UnityEngine.SceneManagement
       .SceneManager.LoadSceneAsync("YourSceneName");

    while (!ao.isDone)
        {
        yield return null;
        }

    // here, the new scene IS LOADED
    SoundBoard soundBoard = Object.FindObjectOfType<SoundBoard>();
    if(soundBoard==null) Debug.Log("WOE!");
    soundBoard.SomeFunctionInSoundboardScript();
    }

Note that you wait on ".isDone", rather than watch the float.


(4) #You actually have to have a scene called "preload", which ONLY preloads.

unfortunately the menu scene can not be your preload scene.

You have to actually have a separate preload scene which does nothing but that, "preload".

Note that any "game managers" you have must be on the preload scene. It's a bit annoying but that's how it is.

The purpose of the "preload" scene is to hold any game managers you have.

The only scene that you mark "don't destroy on load" must be only the "preload" scene. It's that simple.

It's a bit of a nuisance but very simple and reliable.

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • Doesn't the SceneManager.LoadSceneAsync, the function I am using right now to load the scene, serve that purpose? I am unaware of any other ways to do this. @JoeBlow https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadSceneAsync.html – Aaron Ge Jul 30 '16 at 18:23
  • I did want to wait until the next frame, and I am aware of the difference between yield return null and yield break. – Aaron Ge Jul 30 '16 at 18:31
  • Hi Aaron, you literally must have a "preload" scene: which does NOTHING other than hold your persistent components (sound effects and the like). Perhaps read this latest written explanation ... http://stackoverflow.com/a/35891919/294884 – Fattie Jul 30 '16 at 18:39
  • Ok, but why is WaitForSeconds() making the game freeze? @JoeBlow – Aaron Ge Jul 30 '16 at 18:43
  • "Ok, but why is WaitForSeconds() making the game freeze" as I said, put in the Debug.Log statements, and tell us the result – Fattie Jul 30 '16 at 19:02