Skip to content

Commit

Permalink
fix: scene change race condition. wait for server to be ready (#339)
Browse files Browse the repository at this point in the history
* fix: scene change race condition. wait for server to be ready

* add tests
  • Loading branch information
uweeby committed Aug 24, 2020
1 parent b4ec01a commit 2ca0340
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Assets/Mirror/Runtime/Messages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public void Serialize(NetworkWriter writer)
}
}

public struct SceneReadyMessage : IMessageBase
{
public void Deserialize(NetworkReader reader) { /* nothing to serialize */ }

public void Serialize(NetworkWriter writer) { /* nothing to serialize */ }
}

public enum SceneOperation : byte
{
Normal,
Expand Down
22 changes: 21 additions & 1 deletion Assets/Mirror/Runtime/NetworkSceneManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public class NetworkSceneManager : MonoBehaviour, INetworkSceneManager
/// </remarks>
public string NetworkSceneName { get; protected set; } = "";

internal AsyncOperation asyncOperation;

public void Start()
{
DontDestroyOnLoad(gameObject);
Expand All @@ -77,6 +79,7 @@ void RegisterClientMessages(INetworkConnection connection)
{
connection.RegisterHandler<NotReadyMessage>(ClientNotReadyMessage);
connection.RegisterHandler<SceneMessage>(ClientSceneMessage);
connection.RegisterHandler<SceneReadyMessage>(ClientSceneReadyMessage);
}

// called after successful authentication
Expand Down Expand Up @@ -120,6 +123,13 @@ internal void ClientSceneMessage(INetworkConnection conn, SceneMessage msg)
StartCoroutine(ApplySceneOperation(msg.sceneName, msg.sceneOperation));
}

internal void ClientSceneReadyMessage(INetworkConnection conn, SceneReadyMessage msg)
{
logger.Log("ClientSceneReadyMessage");

asyncOperation.allowSceneActivation = true;
}

internal void ClientNotReadyMessage(INetworkConnection conn, NotReadyMessage msg)
{
logger.Log("NetworkSceneManager.OnClientNotReadyMessageInternal");
Expand Down Expand Up @@ -244,6 +254,8 @@ internal void OnServerChangeScene(string newSceneName, SceneOperation operation)
/// <param name="sceneName">The name of the new scene.</param>
internal void OnServerSceneChanged(string sceneName, SceneOperation operation)
{
server.SendToAll(new SceneReadyMessage());

ServerSceneChanged.Invoke(sceneName, operation);
}

Expand All @@ -255,7 +267,15 @@ IEnumerator ApplySceneOperation(string sceneName, SceneOperation sceneOperation
{
case SceneOperation.Normal:
NetworkSceneName = sceneName;
yield return SceneManager.LoadSceneAsync(sceneName);
asyncOperation = SceneManager.LoadSceneAsync(sceneName);

//If non host client. Wait for server to finish scene change
if(client && client.Active && !client.IsLocalClient)
{
asyncOperation.allowSceneActivation = false;
}

yield return asyncOperation;
break;
case SceneOperation.LoadAdditive:
// Ensure additive scene is not already loaded since we don't know which was passed in the Scene message
Expand Down
24 changes: 24 additions & 0 deletions Assets/Mirror/Tests/Runtime/NetworkSceneManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,29 @@ public void NetworkSceneNameStringEmptyTest()
{
Assert.That(clientSceneManager.NetworkSceneName.Equals(string.Empty));
}

[Test]
public void AsyncOperationInitStateTest()
{
Assert.That(clientSceneManager.asyncOperation, Is.Null);
}

[Test]
public void AsyncOperationStateTest()
{
clientSceneManager.ClientSceneMessage(null, new SceneMessage { sceneName = "testScene" });

Assert.That(clientSceneManager.asyncOperation, Is.Not.Null);
Assert.That(clientSceneManager.asyncOperation.allowSceneActivation, Is.False);
}

[Test]
public void ClientSceneReadyMessageTest()
{
clientSceneManager.ClientSceneMessage(null, new SceneMessage { sceneName = "testScene" });
clientSceneManager.ClientSceneReadyMessage(null, new SceneReadyMessage());

Assert.That(clientSceneManager.asyncOperation.allowSceneActivation, Is.True);
}
}
}

0 comments on commit 2ca0340

Please sign in to comment.