Files
dungeons/Assets/Scripts/Managers/SceneManager.cs

207 lines
5.7 KiB
C#

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();
}
}