Implement multiplayer scene loading

This commit is contained in:
2024-08-30 20:27:27 +02:00
parent c4ee93c296
commit c9ee891dc6
3 changed files with 174 additions and 22 deletions

View File

@@ -44,4 +44,13 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 324a182340742c54cbdb3967f1916e29, type: 3} m_Script: {fileID: 11500000, guid: 324a182340742c54cbdb3967f1916e29, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
playerController: {fileID: 0} LobbyScene: {fileID: 102900000, guid: eaec6d3575cfd2d42a5f87b082c898c8, type: 3}
EntranceScene: {fileID: 102900000, guid: 07047a8cc3efe2043ad21378467317ee, type: 3}
ForgeScene: {fileID: 102900000, guid: 0850bb9b948948349b83e3612aa421af, type: 3}
lobbySceneName: Lobby
entranceSceneName: Entrance
forgeSceneName: Forge
gameManager: {fileID: 0}
fadeDuration: 2
loadedScene:
m_Handle: 0

View File

@@ -65,6 +65,8 @@ public class PlayerComponent : NetworkBehaviour
private void Start() private void Start()
{ {
StartCoroutine(AddDontDestroyToDependencies());
if (!isSoloRig) return; if (!isSoloRig) return;
audioListener.enabled = true; audioListener.enabled = true;
@@ -108,6 +110,16 @@ public class PlayerComponent : NetworkBehaviour
} }
} }
private IEnumerator AddDontDestroyToDependencies()
{
yield return new WaitForEndOfFrame();
foreach (var d in dependencies)
{
DontDestroyOnLoad(d);
}
}
public void DestroyDependencies() public void DestroyDependencies()
{ {
foreach (var d in dependencies) foreach (var d in dependencies)
@@ -121,7 +133,7 @@ public class PlayerComponent : NetworkBehaviour
public void Toggle(bool active) public void Toggle(bool active)
{ {
// Only toggle solo rig components, not multiplayer one // Only toggle solo rig components, not multiplayer one
if (isSoloRig) if (networkObject == null || isSoloRig)
{ {
foreach (var d in dependencies) foreach (var d in dependencies)
{ {

View File

@@ -9,13 +9,40 @@ using Zenject;
public class SceneManager : NetworkBehaviour public class SceneManager : NetworkBehaviour
{ {
enum Scene #if UNITY_EDITOR
public UnityEditor.SceneAsset LobbyScene;
public UnityEditor.SceneAsset EntranceScene;
public UnityEditor.SceneAsset ForgeScene;
private void OnValidate()
{ {
Lobby = 0, lobbySceneName = LobbyScene?.name;
Entrance = 1, entranceSceneName = EntranceScene?.name;
Forge = 2 forgeSceneName = ForgeScene?.name;
} }
#endif
[SerializeField]
[ReadOnly]
private string lobbySceneName;
[SerializeField]
[ReadOnly]
private string entranceSceneName;
[SerializeField]
[ReadOnly]
private string forgeSceneName;
//enum Scene
//{
// Lobby = 0,
// Entrance = 1,
// Forge = 2
//}
[Inject] [Inject]
[ReadOnly] [ReadOnly]
[SerializeField] [SerializeField]
@@ -27,35 +54,139 @@ public class SceneManager : NetworkBehaviour
[ReadOnly] [ReadOnly]
[SerializeField] [SerializeField]
private Scene scene; private Scene loadedScene;
public override void OnNetworkSpawn()
{
NetworkManager.SceneManager.OnSceneEvent += OnSceneEvent;
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;
}
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] [Button]
public void SwitchToEntranceLevel() public void SwitchToEntranceLevel()
{ {
StartCoroutine(SwitchToScene(Scene.Entrance)); StartCoroutine(SwitchToSceneMultiplayer(entranceSceneName));
} }
private IEnumerator SwitchToScene(Scene scene) private IEnumerator SwitchToSceneMultiplayer(string scene)
{ {
gameManager.LocalPlayer.FadeScreen(1, fadeDuration); //gameManager.LocalPlayer.FadeScreen(1, fadeDuration);
var operation = UnityEngine.SceneManagement.SceneManager NetworkManager.SceneManager.LoadScene(scene, LoadSceneMode.Single);
.LoadSceneAsync((int)scene);
operation.allowSceneActivation = false; //var operation = UnityEngine.SceneManagement.SceneManager
// .LoadSceneAsync((int)scene);
float timer = 0;
while (timer <= fadeDuration && !operation.isDone) //operation.allowSceneActivation = false;
{
timer += Time.deltaTime; //float timer = 0;
//while (timer <= fadeDuration && !operation.isDone)
//{
// timer += Time.deltaTime;
yield return null; yield return null;
} //}
operation.allowSceneActivation = true; //operation.allowSceneActivation = true;
this.scene = scene; //this.scene = scene;
gameManager.LocalPlayer.FadeScreen(0, fadeDuration); //gameManager.LocalPlayer.FadeScreen(0, fadeDuration);
} }
//private IEnumerator SwitchToSceneSolo(Scene scene)
//{
// gameManager.LocalPlayer.FadeScreen(1, fadeDuration);
// //NetworkManager.SceneManager.LoadScene()
// 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);
//}
} }