Code Samples

A sample of code from a Unity Scenemanager I made for a game jam.

public class SceneLoader : MonoBehaviour, IEventListener
{
    [System.Serializable]
    public class SceneGroup
    {
        public string name;
        public List<int> indices;
    }

    [SerializeField] private List<SceneGroup> sceneGroups;
    [SerializeField] private GameObject loadScreenCamera;
    [SerializeField] private GameObject loadScreenCanvas;

    List<int> activeSceneIndices;
    private int numLoadedScenes = -1;
    private int numScenesMaintained = 0;
    private EventManager eventManager;
    private Coroutine isLoading = null;

    // Start is called before the first frame update
    private void Awake()
    {
        Team2Proj.GameCore.Instance.Build();

        Application.targetFrameRate = 90;
        //Cursor.visible = false;
        activeSceneIndices = new List<int>();
        FullUnloadThenLoad(sceneGroups[1].indices);

        eventManager = EventManager.GetInstance();
    }

    void OnEnable()
    {
        SceneManager.sceneLoaded += CheckSceneLoading;
        SceneManager.sceneUnloaded += CheckSceneUnloading;
    }

    void OnDisable()
    {
        SceneManager.sceneLoaded -= CheckSceneLoading;
        SceneManager.sceneUnloaded -= CheckSceneUnloading;
    }

    public void FullUnloadThenLoadByName(string sceneName)
    {
        SceneGroup matchingItem = sceneGroups.Where(item => item.name == sceneName).First();
        FullUnloadThenLoad(matchingItem.indices);
    }

    void FullUnloadThenLoad(List<int> indices)
    {   
        //if we aren't already loading something
        if (isLoading == null)
        {
            //activate loading screen
            if (loadScreenCamera && loadScreenCanvas)
            {
                loadScreenCanvas.SetActive(true);
                loadScreenCamera.SetActive(true);
            }
            //then start the loading coroutine
            isLoading = StartCoroutine(LoadScenes(indices));
        }
    }

    public void AdditiveLoadByName(string sceneName)
    {
        SceneGroup matchingItem = sceneGroups.Where(item => item.name == sceneName).First();
        AdditiveLoad(matchingItem.indices);
    }

    void AdditiveLoad(List<int> indices)
    {
         foreach (int index in indices)
        {
            if (activeSceneIndices.Contains(index))
            {
                Debug.LogError("Attempted to load already loaded scene with index " + index);
                return;
            }
        }
        
        //if we aren't already loading something
        if (isLoading == null)
        {
            //activate loading screen
            if (loadScreenCamera && loadScreenCanvas)
            {
                loadScreenCanvas.SetActive(true);
                loadScreenCamera.SetActive(true);
            }
            //then start the loading coroutine
            isLoading = StartCoroutine(LoadWithoutUnload(indices));
        }
    }
   

    public void UnloadScenesByName(string sceneName)
    {
        SceneGroup matchingItem = sceneGroups.Where(item => item.name == sceneName).First();
        UnloadScenes(matchingItem.indices);
    }

    void UnloadScenes(List<int> indices)
    {
        foreach (int index in indices)
        {
            if (!activeSceneIndices.Contains(index))
            {
                Debug.LogError("Attempted to unload currently unloaded scene with index " + index);
                return;
            }
        }
        //if we aren't already loading something
        if (isLoading == null)
        {
            //activate loading screen
            if (loadScreenCamera && loadScreenCanvas)
            {
                loadScreenCanvas.SetActive(true);
                loadScreenCamera.SetActive(true);
            }
            //then start the loading coroutine
            isLoading = StartCoroutine(UnloadSome(indices));
        }
    }

    private IEnumerator LoadWithoutUnload(List<int> indices)
    {
        //load the new set of scenes and store their indices
        for (int i = 0; i < indices.Count; ++i)
        {
            activeSceneIndices.Add(indices[i]);
            SceneManager.LoadSceneAsync(indices[i], LoadSceneMode.Additive);
        }


        //wait for all new scenes to be loaded
        do
        {
            yield return new WaitForEndOfFrame();
        } while (numLoadedScenes != numScenesMaintained + indices.Count);

        
        //deactivate the loading screen
        if (loadScreenCamera && loadScreenCanvas)
        {
            loadScreenCanvas.SetActive(false);
            loadScreenCamera.SetActive(false);
        }
        isLoading = null;
    }

    private IEnumerator UnloadSome(List<int> indices)
    {
        int currentScenesLoaded = numLoadedScenes;
        foreach (int index in indices)
        {
            if (activeSceneIndices.Contains(index))
            {
                SceneManager.UnloadSceneAsync(index);
                activeSceneIndices.Remove(index);
            }
        }

        //wait for scenes to be unloaded
        do
        {
            yield return new WaitForEndOfFrame();
        } while (numLoadedScenes != currentScenesLoaded - indices.Count);


        //deactivate the loading screen
        if (loadScreenCamera && loadScreenCanvas)
        {
            loadScreenCanvas.SetActive(false);
            loadScreenCamera.SetActive(false);
        }
        isLoading = null;
    }

    private IEnumerator LoadScenes(List<int> indices)
    {   
        //unload all active scenes
        for (int i = 0; i < activeSceneIndices.Count; ++i)
        {
            SceneManager.UnloadSceneAsync(activeSceneIndices[i]);
        }


        //wait for all old scenes to be unloaded
        do
        {
            yield return new WaitForEndOfFrame();
        } while (numLoadedScenes != numScenesMaintained);

        numScenesMaintained = numLoadedScenes;

        //clear old scene indices
        activeSceneIndices.Clear();

        //load the new set of scenes and store their indices
        for (int i = 0; i < indices.Count; ++i)
        {
            activeSceneIndices.Add(indices[i]);
            SceneManager.LoadSceneAsync(indices[i], LoadSceneMode.Additive);
        }


        //wait for all new scenes to be loaded
        do
        {
            yield return new WaitForEndOfFrame();
        } while (numLoadedScenes != numScenesMaintained + indices.Count);

        numScenesMaintained = numLoadedScenes;

        //deactivate the loading screen
        if (loadScreenCamera && loadScreenCanvas)
        {
            loadScreenCanvas.SetActive(false);
            loadScreenCamera.SetActive(false);
        }
        isLoading = null;
    }

    void CheckSceneLoading(Scene scene, LoadSceneMode mode)
    {
        ++numLoadedScenes;
    }

    void CheckSceneUnloading(Scene scene)
    {
        --numLoadedScenes;
    }

    public void HandleEvent(Event incomingEvent)
    {
        switch (incomingEvent.GetEventType())
        {
        }
    }