Skip to content

Commit b9a092e

Browse files
CarsonKomponhandsomematt
authored andcommitted
Game.ChangeScene shows a loading screen for all clients instead of just the host
1 parent 1cb6485 commit b9a092e

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

engine/Sandbox.Engine/Game/Game/Game.Scene.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ public static bool ChangeScene( SceneLoadOptions options )
3535
if ( !Networking.IsHost )
3636
return false;
3737

38+
// Tell clients the host is about to load a new scene before we start,
39+
// so we show a loading screen immediately rather than freezing silently.
40+
SceneNetworkSystem.Instance?.NotifySceneChangeStarting( options );
41+
3842
// We don't want to send any networked messages to do with deletion or creation
3943
// of GameObjects here. Because the client will destroy their scene locally
4044
// anyway. This saves us sending a message for potentially 100s of objects.

engine/Sandbox.Engine/Scene/Networking/SceneNetworkSystem.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ internal SceneNetworkSystem( Internal.TypeLibrary typeLibrary, NetworkSystem sys
4646
AddHandler<SceneRpcMsg>( OnSceneRpc );
4747
AddHandler<StaticRpcMsg>( OnStaticRpc );
4848
AddHandler<LoadSceneBeginMsg>( OnLoadSceneMsg );
49+
AddHandler<LoadSceneNotifyMsg>( OnLoadSceneNotifyMsg );
4950
AddHandler<LoadSceneSnapshotMsg>( OnLoadSceneSnapshotMsg );
5051
AddHandler<LoadSceneRequestSnapshotMsg>( OnLoadSceneRequestSnapshotMsg );
5152
AddHandler<SceneLoadedMsg>( OnSceneLoadedMsg );
@@ -84,6 +85,35 @@ internal static IDisposable SuppressDestroyMessages()
8485

8586
private readonly Dictionary<Guid, Guid> PendingSceneLoads = new();
8687

88+
/// <summary>
89+
/// Notify all connected clients that the host is loading a new scene.
90+
/// Sent before <see cref="LoadSceneBroadcast"/> so clients can show a loading screen immediately rather than freezing with no feedback.
91+
/// </summary>
92+
internal void NotifySceneChangeStarting( SceneLoadOptions options )
93+
{
94+
if ( !Networking.IsActive || !Networking.IsHost )
95+
return;
96+
97+
var msg = new LoadSceneNotifyMsg { ShowLoadingScreen = options.ShowLoadingScreen };
98+
99+
var bs = ByteStream.Create( 64 );
100+
bs.Write( InternalMessageType.Packed );
101+
Networking.System.Serialize( msg, ref bs );
102+
103+
foreach ( var c in Connection.All )
104+
{
105+
if ( c == Connection.Local )
106+
continue;
107+
108+
if ( c.State < Connection.ChannelState.Snapshot )
109+
continue;
110+
111+
c.SendStream( bs );
112+
}
113+
114+
bs.Dispose();
115+
}
116+
87117
/// <summary>
88118
/// Load a scene for all other clients. This can only be called by the host.
89119
/// </summary>
@@ -302,6 +332,21 @@ private async Task OnLoadSceneRequestSnapshotMsg( LoadSceneRequestSnapshotMsg ms
302332
bs.Dispose();
303333
}
304334

335+
/// <summary>
336+
/// Called when the host notifies us it is about to begin loading a new scene.
337+
/// </summary>
338+
private void OnLoadSceneNotifyMsg( LoadSceneNotifyMsg msg, Connection connection, Guid msgId )
339+
{
340+
if ( Game.IsEditor )
341+
return;
342+
343+
if ( msg.ShowLoadingScreen )
344+
{
345+
LoadingScreen.IsVisible = true;
346+
LoadingScreen.Title = "Loading Scene";
347+
}
348+
}
349+
305350
/// <summary>
306351
/// Called when the host has told us to load a new scene.
307352
/// </summary>
@@ -1375,6 +1420,12 @@ struct ObjectRefreshMsg
13751420
public Guid Guid { get; set; }
13761421
}
13771422

1423+
[Expose]
1424+
struct LoadSceneNotifyMsg
1425+
{
1426+
public bool ShowLoadingScreen { get; set; }
1427+
}
1428+
13781429
[Expose]
13791430
struct LoadSceneBeginMsg
13801431
{

0 commit comments

Comments
 (0)