using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.SceneManagement; /// /// This class manages the scene loading and unloading. /// public class SceneLoader : MonoBehaviour { [SerializeField] private GameSceneSO _gameplayScene = default; [Header("Load Events")] [SerializeField] private LoadEventChannelSO _loadLocation = default; [SerializeField] private LoadEventChannelSO _loadMenu = default; [Header("Broadcasting on")] [SerializeField] private BoolEventChannelSO _toggleLoadingScreen = default; [SerializeField] private VoidEventChannelSO _onSceneReady = default; private AsyncOperationHandle _loadingOperationHandle; private AsyncOperationHandle _gameplayManagerLoadingOpHandle; //Parameters coming from scene loading requests private GameSceneSO _sceneToLoad; private GameSceneSO _currentlyLoadedScene; private bool _showLoadingScreen; private SceneInstance _gameplayManagerSceneInstance = new SceneInstance(); private void OnEnable() { _loadLocation.OnLoadingRequested += LoadLocation; _loadMenu.OnLoadingRequested += LoadMenu; } private void OnDisable() { _loadLocation.OnLoadingRequested -= LoadLocation; _loadMenu.OnLoadingRequested -= LoadMenu; } /// /// This function loads the location scenes passed as array parameter /// private void LoadLocation(GameSceneSO locationToLoad, bool showLoadingScreen) { _sceneToLoad = locationToLoad; _showLoadingScreen = showLoadingScreen; //In case we are coming from the main menu, we need to load the Gameplay manager scene first if (_gameplayManagerSceneInstance.Scene == null || !_gameplayManagerSceneInstance.Scene.isLoaded) { _gameplayManagerLoadingOpHandle = _gameplayScene.sceneReference.LoadSceneAsync(LoadSceneMode.Additive, true); _gameplayManagerLoadingOpHandle.Completed += OnGameplayMangersLoaded; } else { UnloadPreviousScene(); } } private void OnGameplayMangersLoaded(AsyncOperationHandle obj) { _gameplayManagerSceneInstance = _gameplayManagerLoadingOpHandle.Result; UnloadPreviousScene(); } /// /// Prepares to load the main menu scene, first removing the Gameplay scene in case the game is coming back from gameplay to menus. /// private void LoadMenu(GameSceneSO menuToLoad, bool showLoadingScreen) { _sceneToLoad = menuToLoad; _showLoadingScreen = showLoadingScreen; //In case we are coming from a Location back to the main menu, we need to get rid of the persistent Gameplay manager scene if (_gameplayManagerSceneInstance.Scene != null && _gameplayManagerSceneInstance.Scene.isLoaded) Addressables.UnloadSceneAsync(_gameplayManagerLoadingOpHandle, true); UnloadPreviousScene(); } /// /// In both Location and Menu loading, this function takes care of removing previously loaded temporary scenes. /// private void UnloadPreviousScene() { if(_currentlyLoadedScene != null) _currentlyLoadedScene.sceneReference.UnLoadScene(); LoadNewScene(); } /// /// Kicks off the asynchronous loading of a scene, either menu or Location. /// private void LoadNewScene() { if (_showLoadingScreen) { _toggleLoadingScreen.RaiseEvent(true); } _loadingOperationHandle = _sceneToLoad.sceneReference.LoadSceneAsync(LoadSceneMode.Additive, true, 0); _loadingOperationHandle.Completed += OnNewSceneLoaded; } private void OnNewSceneLoaded(AsyncOperationHandle obj) { //Save loaded scenes (to be unloaded at next load request) _currentlyLoadedScene = _sceneToLoad; SetActiveScene(); if (_showLoadingScreen) { _toggleLoadingScreen.RaiseEvent(false); } } /// /// This function is called when all the scenes have been loaded /// private void SetActiveScene() { Scene s = ((SceneInstance)_loadingOperationHandle.Result).Scene; SceneManager.SetActiveScene(s); LightProbes.TetrahedralizeAsync(); _onSceneReady.RaiseEvent(); //Spawn system will spawn the PigChef } private void ExitGame() { Application.Quit(); Debug.Log("Exit!"); } }