(Fix) Loading Screen
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using FishNet;
|
||||
using FishNet.Connection;
|
||||
@@ -29,6 +30,10 @@ namespace Ashwild.Network
|
||||
[Tooltip("The single source of truth for the gameplay scene loaded over the network.")]
|
||||
[SerializeField] private string gameSceneName = "TestScene";
|
||||
|
||||
[Tooltip("Max seconds to wait for the loading curtain to fully fade in before loading the game " +
|
||||
"scene anyway. Safety net so a missing/disabled LoadingScreen can never soft-lock the host.")]
|
||||
[SerializeField] private float curtainWaitTimeout = 3f;
|
||||
|
||||
[Header("Player")]
|
||||
[Tooltip("The networked player prefab (NetworkObject + PlayerNetworkController).")]
|
||||
[SerializeField] private NetworkObject playerPrefab;
|
||||
@@ -61,6 +66,12 @@ namespace Ashwild.Network
|
||||
/// </summary>
|
||||
private bool pendingSceneLoad;
|
||||
|
||||
/// <summary>
|
||||
/// Set once the loading curtain has fully faded in; gates the heavy game scene load so the
|
||||
/// activation freeze happens behind an opaque curtain. Reset at the start of every host launch.
|
||||
/// </summary>
|
||||
private bool curtainShown;
|
||||
|
||||
/// <summary>
|
||||
/// Round-robin cursor over the available spawn points.
|
||||
/// </summary>
|
||||
@@ -107,6 +118,7 @@ namespace Ashwild.Network
|
||||
networkManager.ServerManager.OnRemoteConnectionState += HandleRemoteState;
|
||||
networkManager.ClientManager.OnClientConnectionState += HandleClientState;
|
||||
networkManager.SceneManager.OnClientPresenceChangeEnd += HandleClientPresenceEnd;
|
||||
PlayerEvents.LoadingCurtainShown += HandleLoadingCurtainShown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -120,6 +132,7 @@ namespace Ashwild.Network
|
||||
networkManager.ServerManager.OnRemoteConnectionState -= HandleRemoteState;
|
||||
networkManager.ClientManager.OnClientConnectionState -= HandleClientState;
|
||||
networkManager.SceneManager.OnClientPresenceChangeEnd -= HandleClientPresenceEnd;
|
||||
PlayerEvents.LoadingCurtainShown -= HandleLoadingCurtainShown;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -151,6 +164,7 @@ namespace Ashwild.Network
|
||||
PlayerEvents.RaiseSessionStarting();
|
||||
Log("Starting host (server + client) over Steam…");
|
||||
|
||||
curtainShown = false;
|
||||
pendingSceneLoad = true;
|
||||
|
||||
bool serverOk = networkManager.ServerManager.StartConnection();
|
||||
@@ -215,6 +229,26 @@ namespace Ashwild.Network
|
||||
if (networkManager.ServerManager.Started) networkManager.ServerManager.StopConnection(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Leaves the current session and returns to the menu scene behind the loading curtain. Mirrors
|
||||
/// the host launch: it raises the curtain, waits for it to fully fade in (so the menu-load freeze
|
||||
/// is hidden), tears the session down, loads the menu, then signals MenuReady to drop the curtain.
|
||||
/// Orchestrated here — not on the per-scene GameUIManager — because this object persists across
|
||||
/// the scene swap while the caller is destroyed by the load.
|
||||
/// </summary>
|
||||
public void ReturnToMenu(string menuSceneName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(menuSceneName))
|
||||
{
|
||||
Debug.LogError("[NetworkSession] ReturnToMenu called with no menu scene name.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerEvents.RaiseReturningToMenu();
|
||||
curtainShown = false;
|
||||
StartCoroutine(ReturnToMenuRoutine(menuSceneName));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Connection Handlers
|
||||
@@ -235,7 +269,7 @@ namespace Ashwild.Network
|
||||
if (pendingSceneLoad)
|
||||
{
|
||||
pendingSceneLoad = false;
|
||||
LoadGameSceneNetworked();
|
||||
StartCoroutine(LoadGameSceneWhenCurtainShown());
|
||||
}
|
||||
}
|
||||
else if (args.ConnectionState == LocalConnectionState.Stopped)
|
||||
@@ -268,6 +302,12 @@ namespace Ashwild.Network
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The loading curtain finished fading in — release the gate so the deferred game scene
|
||||
/// load can proceed (see <see cref="LoadGameSceneWhenCurtainShown"/>).
|
||||
/// </summary>
|
||||
private void HandleLoadingCurtainShown() => curtainShown = true;
|
||||
|
||||
/// <summary>
|
||||
/// A *remote* client connected to or disconnected from our server; updates the count.
|
||||
/// </summary>
|
||||
@@ -343,6 +383,53 @@ namespace Ashwild.Network
|
||||
|
||||
#region Internal Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Defers the heavy networked scene load until the loading curtain has fully faded in
|
||||
/// (PlayerEvents.LoadingCurtainShown), so the unavoidable activation freeze of a big scene
|
||||
/// happens behind an already-opaque curtain instead of stalling the frame the curtain was
|
||||
/// meant to appear on. Falls back to loading anyway after <see cref="curtainWaitTimeout"/> so
|
||||
/// a missing or disabled LoadingScreen can never soft-lock the host. Runs on unscaled time.
|
||||
/// </summary>
|
||||
private IEnumerator LoadGameSceneWhenCurtainShown()
|
||||
{
|
||||
float start = Time.unscaledTime;
|
||||
while (!curtainShown && Time.unscaledTime - start < curtainWaitTimeout)
|
||||
yield return null;
|
||||
|
||||
if (!curtainShown)
|
||||
Log($"Loading curtain not reported within {curtainWaitTimeout}s — loading scene anyway.");
|
||||
|
||||
LoadGameSceneNetworked();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for the curtain to fully fade in (or the timeout), tears the session down, loads the
|
||||
/// menu scene locally (Single — the persistent NetworkManager survives), then raises MenuReady
|
||||
/// so the curtain drops once the menu is up. Runs on the persistent NetworkManager object so it
|
||||
/// outlives the game scene being unloaded. Uses unscaled time.
|
||||
/// </summary>
|
||||
private IEnumerator ReturnToMenuRoutine(string menuSceneName)
|
||||
{
|
||||
float start = Time.unscaledTime;
|
||||
while (!curtainShown && Time.unscaledTime - start < curtainWaitTimeout)
|
||||
yield return null;
|
||||
|
||||
StopSession();
|
||||
|
||||
AsyncOperation op = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(menuSceneName, LoadSceneMode.Single);
|
||||
if (op != null)
|
||||
{
|
||||
while (!op.isDone)
|
||||
yield return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"[NetworkSession] Could not load menu scene '{menuSceneName}' — is it in Build Settings?", this);
|
||||
}
|
||||
|
||||
PlayerEvents.RaiseMenuReady();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the gameplay scene as a global networked scene, replacing the menu.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user