André Gasser
André Gasser

Reputation: 1105

Scene not properly loaded when switching back and forth

Problem
The Unity project I build is targeting iOS, Android and Windows X64. I have two scenes, A and B, whereas A is the main menu scene of my game and scene B is kind of a level selection scene in which the user can choose a level to play. From scene A I can navigate to scene B and back again. When running the game in the Unity Editor, everything behaves as expected. The problem arises, when I run the game on the target platforms (real devices). Then, when navigating like A --> B --> A, I end up in scene A being rendered as a black screen, except the FPSIndicator game object which is still rendered and doing its job. The FPSIndicator game object is a small piece of code which draws itself to the scene in the OnGUI callback. Nothing else is displayed.

Setup of Scene A
I have a Unity UI button there ("Drag and Drop"), which, when clicked, loads scene B using this code:

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

public class GameTypeButtonController : MonoBehaviour, IPointerClickHandler
{
    public ButtonSounds ButtonSounds;
    public string SceneNameToLoad;
    public GameType GameType;

    public void OnPointerClick(PointerEventData eventData)
    {
        StartCoroutine(Do());
    }

    private IEnumerator Do()
    {
        var animator = gameObject.GetComponent<Animator>();

        if (animator != null)
        {
            animator.SetTrigger("Clicked");
        }

        var audioSource = gameObject.GetComponent<AudioSource>();

        if (audioSource != null)
        {
            var clip = GetRandomAudioClip(ButtonSounds);
            audioSource.clip = clip;
            audioSource.Play();
            yield return new WaitWhile(() => audioSource.isPlaying);
        }

        Logger.LogInfo("[GameTypeButtonController.Do] Setting game type " + GameType);
        GameManager.Instance.CurrentGameType = GameType;
        SceneManager.LoadScene(SceneNameToLoad);
    }

    private AudioClip GetRandomAudioClip(ButtonSounds buttonSounds)
    {
        var numberOfAudioClips = buttonSounds.AudioClips.Length;
        var randomIndex = Random.Range(0, numberOfAudioClips);
        return buttonSounds.AudioClips[randomIndex];
    }
}

The scene looks like this:

enter image description here

Setup of Scene B
In scene B, I have a button in the lower left which brings me back to scene A when clicked. This is not a Unity UI button, but a regular sprite with a CircleCollider2D attached. The script on that button looks like this:

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

public class HomeButtonController : MonoBehaviour
{
    public ButtonSounds ButtonSounds;
    public string SceneNameToLoad;

    void OnMouseDown()
    {
        StartCoroutine(Do());
    }

    private IEnumerator Do()
    {
        var animator = gameObject.GetComponent<Animator>();

        if (animator != null)
        {
            animator.SetTrigger("Clicked");
        }

        var audioSource = gameObject.GetComponent<AudioSource>();

        if (audioSource != null)
        {
            var clip = GetRandomAudioClip(ButtonSounds);
            audioSource.clip = clip;
            audioSource.Play();
            yield return new WaitWhile(() => audioSource.isPlaying);
        }

        SceneManager.LoadScene(SceneNameToLoad);
    }

    private AudioClip GetRandomAudioClip(ButtonSounds buttonSounds)
    {
        var numberOfAudioClips = buttonSounds.AudioClips.Length;
        var randomIndex = UnityEngine.Random.Range(0, numberOfAudioClips);
        return buttonSounds.AudioClips[randomIndex];
    }
}

The scene looks like this:

enter image description here

General Notes
Two objects use DontDestroyOnLoad: GameManager and MusicPlayer.

What I have checked so far

Update 2019-02-19:
When I navigate from a third scene C back to scene A using the same mechanism (a sprite button calling a coroutine), I also end up on the very same black screen. So the issue probably exists within scene A?

Update 2 from 2019-02-19:
Here's my GameManager code:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;

public class GameManager : MonoBehaviour
{
    public EventHandler<LevelStartedEventArgs> LevelStarted;
    public EventHandler<LevelFinishedEventArgs> LevelFinished;

    // General 
    public GameType CurrentGameType;
    public GameScene CurrentScene;
    public int CurrentLevel;
    public static GameManager Instance;
    public GameLanguage Language;
    public bool IsMusicEnabled;
    private string gameStateFile;

    void Start()
    {
        if (Instance == null)
        {
            gameStateFile = Application.persistentDataPath + "/gamestate.dat";
            Load(gameStateFile);
            DontDestroyOnLoad(gameObject);
            Instance = this;
        }
        else if (Instance != this)
        {
            Destroy(gameObject);
        }
    }

    public void Save()
    {
        Logger.LogInfo("[GameManager.Save] Saving game state to " + gameStateFile);
        var bf = new BinaryFormatter();
        var file = File.Create(gameStateFile);

        var gameState = new GameState();
        gameState.Language = Language;
        gameState.IsMusicEnabled = IsMusicEnabled;

        bf.Serialize(file, gameState);
        file.Close();
        Logger.LogInfo("[GameManager.Save] Successfully saved game state");
    }

    public void Load(string gameStateFile)
    {
        Logger.LogInfo("[GameManager.Load] Loading game state from " + gameStateFile);
        if (File.Exists(gameStateFile))
        {
            var bf = new BinaryFormatter();
            var file = File.Open(gameStateFile, FileMode.Open);
            var gameState = (GameState)bf.Deserialize(file);
            file.Close();
            Language = gameState.Language;
            IsMusicEnabled = gameState.IsMusicEnabled;
        }
        Logger.LogInfo("[GameManager.Load] Successfully loaded game state");
    }

    [Serializable]
    class GameState {
        public GameLanguage Language;
        public bool IsMusicEnabled;
    }
}

Thanks for any hints!

Upvotes: 1

Views: 1770

Answers (1)

Andr&#233; Gasser
Andr&#233; Gasser

Reputation: 1105

So, I finally managed to solve the issue on my own. Here's a list of steps I went through in order to eliminate my issue:

  1. I installed the "Game development with Unity" workload in Visual Studio 2017 in order to be able to use the Visual Studio Debugger. That gave me the possibility to properly debug my scripts (setting breakpoints, inspect values, ...) and go through them, step by step. See this link for some details on how to accomplish this. Unfortunately, this did not solve my problem yet, but gave a good basis for troubleshooting my issue.

  2. As the issue described above, also arised on Windows x64 builds, I've decided to troubleshoot my issue on a windows build. So I reconfigured my Windows build in the Build Player Settings, by setting Script Debugging to true, Development build to true, Copy PDB filesto true. Then I've ran another windows build.

If you now run your game, it will show a development console in the lower left screen, giving a lot of useful information (exceptions thrown, etc...). Also you can open the log file directly from within the game, which provides a LOT of useful informations to tackle down the real issue.

So, I had some PlatformNotSupportedExceptions in the logs, which I was able to fix and some other errors. Now it is working.

Although, I've answered my own question, I hope this will be useful to some of you.

Upvotes: 1

Related Questions