using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
///
/// This class manages the scene loading and unloading.
/// Heavy on comments right now because it is still being worked on.
///
public class LocationLoader : MonoBehaviour
{
[Header("Initialization Scene")]
[SerializeField] private GameSceneSO _initializationScene = default;
[Header("Load on start")]
[SerializeField] private GameSceneSO[] _mainMenuScenes = default;
[Header("Loading Screen")]
[SerializeField] private GameObject _loadingInterface = default;
[SerializeField] private Image _loadingProgressBar = default;
[Header("Load Event")]
//The load event we are listening to
[SerializeField] private LoadEventChannelSO _loadEventChannel = default;
private List _scenesToLoadAsyncOperations = new List();
private List _scenesToUnload = new List();
private GameSceneSO _activeScene; // The scene we want to set as active (for lighting/skybox)
private Coroutine runningLoader = null;
private void OnEnable()
{
_loadEventChannel.OnLoadingRequested += LoadScenes;
}
private void OnDisable()
{
_loadEventChannel.OnLoadingRequested -= LoadScenes;
}
private void Start()
{
if (SceneManager.GetActiveScene().name == _initializationScene.sceneName)
{
LoadMainMenu();
}
}
private void LoadMainMenu()
{
LoadScenes(_mainMenuScenes, false);
}
///
/// This function loads the scenes passed as array parameter
///
///
///
private void LoadScenes(GameSceneSO[] locationsToLoad, bool showLoadingScreen)
{
_activeScene = locationsToLoad[0];
AddScenesToUnload();
UnloadScenes();
if (showLoadingScreen)
{
_loadingInterface.SetActive(true);
}
if (_scenesToLoadAsyncOperations.Count == 0)
{
for (int i = 0; i < locationsToLoad.Length; i++)
{
string currentSceneName = locationsToLoad[i].sceneName;
if (IsSceneLoaded(currentSceneName) == false)
{
if (runningLoader == null)
{
_scenesToLoadAsyncOperations.Add(SceneManager.LoadSceneAsync(currentSceneName, LoadSceneMode.Additive));
_scenesToLoadAsyncOperations[i].completed += SetActiveScene;
// TODO: Run a coroutine for each scene loading that updates a combined value
// for the progress bar. This way, as each scene completes loading, we will
// know what scene it is. Then decide if it activates right away or not.
// runningLoader = StartCoroutine(TrackLoadingProgress(locationsToLoad[i]));
}
}
}
if (_scenesToLoadAsyncOperations.Count > 0)
{
// TODO: locationsToLoad[0] is a place holder right now.
runningLoader = StartCoroutine(TrackLoadingProgress(locationsToLoad[0]));
}
}
}
///
/// SetActiveScene(AsyncOperation asyncOp) is called by AsyncOperation.complete event.
///
///
private void SetActiveScene(AsyncOperation asyncOp)
{
// TODO: As each event completes, decide if it needs to activate right away.
SceneManager.SetActiveScene(SceneManager.GetSceneByName(_activeScene.sceneName));
}
private void AddScenesToUnload()
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.name != _initializationScene.sceneName && scene.name != _activeScene.name)
{
Debug.Log("Added scene to unload = " + scene.name);
_scenesToUnload.Add(scene);
}
}
}
private void UnloadScenes()
{
if (_scenesToUnload != null)
{
for (int i = 0; i < _scenesToUnload.Count; i++)
{
SceneManager.UnloadSceneAsync(_scenesToUnload[i]);
}
_scenesToUnload.Clear();
}
}
///
/// This function checks if a scene is already loaded
///
///
/// bool
private bool IsSceneLoaded(string sceneName)
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.name == sceneName)
{
return true;
}
}
return false;
}
///
/// This function updates the loading progress once per frame until loading is complete
///
/// This is a place holder for the moment
/// IEnumerator
private IEnumerator TrackLoadingProgress(GameSceneSO sceneReference)
{
float totalProgress = 0;
// When the scene reaches 0.9f, it means that it is loaded
// The remaining 0.1f are for the integration
while (totalProgress <= 0.9f)
{
totalProgress = 0;
for (int i = 0; i < _scenesToLoadAsyncOperations.Count; ++i)
{
Debug.Log("Scene " + i + " :" + _scenesToLoadAsyncOperations[i].isDone + " progress = " + _scenesToLoadAsyncOperations[i].progress);
totalProgress += _scenesToLoadAsyncOperations[i].progress;
}
//The fillAmount is for all scenes, so we divide the progress by the number of scenes to load
_loadingProgressBar.fillAmount = totalProgress / _scenesToLoadAsyncOperations.Count;
Debug.Log("progress bar " + _loadingProgressBar.fillAmount + " and value = " + totalProgress / _scenesToLoadAsyncOperations.Count);
yield return null;
}
_scenesToLoadAsyncOperations.Clear();
runningLoader = null;
//Hide progress bar when loading is done
_loadingInterface.SetActive(false);
}
private void ExitGame()
{
Application.Quit();
Debug.Log("Exit!");
}
}