using Sirenix.OdinInspector; using System.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using Zenject; public class SceneManager : NetworkBehaviour { [SerializeField] private Level lobbyLevel; [SerializeField] private Level entranceLevel; [SerializeField] private Level forgeLevel; public Level[] Levels => new []{ entranceLevel, forgeLevel }; [Inject] [ReadOnly] [SerializeField] private GameManager gameManager; [ReadOnly] [SerializeField] private float fadeDuration = 2f; [ReadOnly] [SerializeField] private Scene loadedScene; public Scene LoadedScene => loadedScene; public bool IsInLobby => loadedScene.name == lobbyLevel.sceneName; public UnityEvent SceneLoaded; private bool isMultiplayer => gameManager.IsMultiplayer; private void Awake() { loadedScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); } public override void OnNetworkSpawn() { NetworkManager.SceneManager.OnSceneEvent += OnSceneEvent; Debug.Log("network spawn"); base.OnNetworkSpawn(); } private void OnSceneEvent(SceneEvent sceneEvent) { var clientOrServer = sceneEvent.ClientId == NetworkManager.ServerClientId ? "server" : "client"; switch (sceneEvent.SceneEventType) { case SceneEventType.LoadComplete: { // We want to handle this for only the server-side if (sceneEvent.ClientId == NetworkManager.ServerClientId) { // Keep track of the loaded scene, you need this to unload it loadedScene = sceneEvent.Scene; SceneLoaded.Invoke(); } Debug.Log($"Loaded the {sceneEvent.SceneName} scene on " + $"{clientOrServer}-({sceneEvent.ClientId})."); break; } case SceneEventType.UnloadComplete: { Debug.Log($"Unloaded the {sceneEvent.SceneName} scene on " + $"{clientOrServer}-({sceneEvent.ClientId})."); break; } case SceneEventType.LoadEventCompleted: case SceneEventType.UnloadEventCompleted: { var loadUnload = sceneEvent.SceneEventType == SceneEventType.LoadEventCompleted ? "Load" : "Unload"; Debug.Log($"{loadUnload} event completed for the following client " + $"identifiers:({sceneEvent.ClientsThatCompleted})"); if (sceneEvent.ClientsThatTimedOut.Count > 0) { Debug.LogWarning($"{loadUnload} event timed out for the following client " + $"identifiers:({sceneEvent.ClientsThatTimedOut})"); } break; } } } private void CheckStatus(SceneEventProgressStatus status, bool isLoading = true) { var sceneEventAction = isLoading ? "load" : "unload"; if (status != SceneEventProgressStatus.Started) { Debug.LogWarning($"Failed to {sceneEventAction} with" + $" a {nameof(SceneEventProgressStatus)}: {status}"); } } private void UnloadScene() { // Assure only the server calls this when the NetworkObject is // spawned and the scene is loaded. if (!IsServer || !IsSpawned || !loadedScene.IsValid() || !loadedScene.isLoaded) { return; } var status = NetworkManager.SceneManager.UnloadScene(loadedScene); CheckStatus(status, false); } [Button] public void SwitchToLobbyLevel() { SwitchToScene(lobbyLevel.sceneName); } [Button] public void SwitchToEntranceLevel() { SwitchToScene(entranceLevel.sceneName); } [Button] public void SwitchToForgeLevel() { SwitchToScene(forgeLevel.sceneName); } private void SwitchToScene(string sceneName) { if (isMultiplayer) { StartCoroutine(SwitchToSceneMultiplayer(sceneName)); } else { StartCoroutine(SwitchToSceneSolo(sceneName)); } } private IEnumerator SwitchToSceneMultiplayer(string scene) { //gameManager.LocalPlayer.FadeScreen(1, fadeDuration); NetworkManager.SceneManager.LoadScene(scene, LoadSceneMode.Single); //var operation = UnityEngine.SceneManagement.SceneManager // .LoadSceneAsync((int)scene); //operation.allowSceneActivation = false; //float timer = 0; //while (timer <= fadeDuration && !operation.isDone) //{ // timer += Time.deltaTime; yield return null; //} //operation.allowSceneActivation = true; //this.scene = scene; //gameManager.LocalPlayer.FadeScreen(0, fadeDuration); } private IEnumerator SwitchToSceneSolo(string scene) { gameManager.LocalPlayer.FadeScreen(1, fadeDuration); var operation = UnityEngine.SceneManagement.SceneManager .LoadSceneAsync(scene); operation.allowSceneActivation = false; float timer = 0; while (timer <= fadeDuration && !operation.isDone) { timer += Time.deltaTime; yield return null; } operation.allowSceneActivation = true; gameManager.LocalPlayer.FadeScreen(0, fadeDuration); loadedScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); } }