Skip to content

fix: not returning to mainmenu when reconnect fails #532

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,21 @@ void OnConnectStatus(ConnectStatus status)
PopupPanel.ShowPopupPanel("Connection Failed", "The Host is full and cannot accept any additional connections.");
break;
case ConnectStatus.Success:
m_PopupIdToClose = PopupPanel.ShowPopupPanel("Success!", "Joining Now", isCloseableByUser: false);
m_PopupIdToClose = PopupPanel.ShowPopupPanel("Success!", "Joining Now...", isCloseableByUser: false);
SceneManager.sceneLoaded += ClosePopupOnsceneLoaded;
break;
case ConnectStatus.LoggedInAgain:
PopupPanel.ShowPopupPanel("Connection Failed", "You have logged in elsewhere using the same account.");
break;
case ConnectStatus.GenericDisconnect:
PopupPanel.ShowPopupPanel("Disconnected From Host", "The connection to the host was lost");
PopupPanel.ShowPopupPanel("Disconnected From Host", "The connection to the host was lost.");
break;
case ConnectStatus.Reconnecting:
m_PopupIdToClose = PopupPanel.ShowPopupPanel("Attempting reconnection", "Lost connection to the Host, attempting to reconnect...", isCloseableByUser: false);
break;
case ConnectStatus.HostDisconnected:
PopupPanel.ShowPopupPanel("Disconnected From Host", "The host has ended the game session.");
break;
default:
Debug.LogWarning($"New ConnectStatus {status} has been added, but no connect message defined for it.");
break;
Expand Down
4 changes: 2 additions & 2 deletions Assets/BossRoom/Scripts/Client/UI/UnityServicesUIHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void ServiceErrorHandler(UnityServiceErrorMessage error)
var errorMessage = error.Message;
if (error.AffectedService == UnityServiceErrorMessage.Service.Lobby)
{
if ((error.OriginalException as LobbyServiceException).Reason == LobbyExceptionReason.LobbyConflict)
if (error.OriginalException is LobbyServiceException {Reason: LobbyExceptionReason.LobbyConflict})
{
// LobbyConflict can have multiple causes. Let's add other solutions here if there's other situations that arise for this.
errorMessage += "\nSee logs for possible causes and solution.";
Expand All @@ -44,4 +44,4 @@ void OnDestroy()
m_Subscriptions.Dispose();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class ClientGameNetPortal : MonoBehaviour
/// Time in seconds before the client considers a lack of server response a timeout
/// </summary>
private const int k_TimeoutDuration = 10;
const int k_NbReconnectAttempts = 1;

/// <summary>
/// This event fires when the client sent out a request to start the client, but failed to hear back after an allotted amount of
Expand Down Expand Up @@ -102,6 +103,20 @@ public void OnUserDisconnectRequest()
StopCoroutine(m_TryToReconnectCoroutine);
m_TryToReconnectCoroutine = null;
}

if (!m_Portal.NetManager.IsConnectedClient)
{
// If we are here, it means we will not receive the OnClientDisconnectCallback since we are already disconnected.
// In that case, publish the disconnect reason and clear it now.
m_ConnectStatusPub.Publish(DisconnectReason.Reason);
DisconnectReason.Clear();
}

// only do it here if we are not the host. The host will do it in ServerGameNetPortal
if (!m_Portal.NetManager.IsHost)
{
m_Portal.NetManager.Shutdown();
}
}
}

Expand Down Expand Up @@ -142,7 +157,7 @@ private void OnDisconnectOrTimeout(ulong clientID)
//We have to check here in SceneManager if our active scene is the main menu, as if it is, it means we timed out rather than a raw disconnect;
if (SceneManager.GetActiveScene().name != "MainMenu")
{
if (DisconnectReason.Reason == ConnectStatus.UserRequestedDisconnect || NetworkManager.Singleton.IsHost)
if (DisconnectReason.Reason == ConnectStatus.UserRequestedDisconnect || DisconnectReason.Reason == ConnectStatus.HostDisconnected || NetworkManager.Singleton.IsHost)
{
// simply shut down and go back to main menu
NetworkManager.Singleton.Shutdown();
Expand Down Expand Up @@ -172,27 +187,24 @@ private IEnumerator TryToReconnect()
{
Debug.Log("Lost connection to host, trying to reconnect...");
int nbTries = 0;
while (nbTries < 3)
while (nbTries < k_NbReconnectAttempts)
{
NetworkManager.Singleton.Shutdown();
yield return new WaitWhile(() => NetworkManager.Singleton.ShutdownInProgress); // wait until NetworkManager completes shutting down
Debug.Log($"Reconnecting attempt {nbTries + 1}/3...");
Debug.Log($"Reconnecting attempt {nbTries + 1}/{k_NbReconnectAttempts}...");
ConnectClient(null);
yield return new WaitForSeconds(1.1f * k_TimeoutDuration); // wait a bit longer than the timeout duration to make sure we have enough time to stop this coroutine if successful
nbTries++;
}

if (!NetworkManager.Singleton.IsConnectedClient)
// If the coroutine has not been stopped before this, it means we failed to connect during all attempts
Debug.Log("All tries failed, returning to main menu");
NetworkManager.Singleton.Shutdown();
SceneLoaderWrapper.Instance.LoadScene("MainMenu");
if (!DisconnectReason.HasTransitionReason)
{
Debug.Log("All tries failed, returning to main menu");
SceneLoaderWrapper.Instance.LoadScene("MainMenu");
if (!DisconnectReason.HasTransitionReason)
{
DisconnectReason.SetDisconnectReason(ConnectStatus.GenericDisconnect);
}

DisconnectReason.SetDisconnectReason(ConnectStatus.GenericDisconnect);
}
NetworkManager.Singleton.Shutdown();
m_TryToReconnectCoroutine = null;
m_ConnectStatusPub.Publish(DisconnectReason.Reason);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using Unity.Multiplayer.Samples.BossRoom.Client;
using Unity.Multiplayer.Samples.BossRoom.Server;
using Unity.Multiplayer.Samples.BossRoom.Shared.Infrastructure;
Expand All @@ -19,6 +20,7 @@ public enum ConnectStatus
UserRequestedDisconnect, //Intentional Disconnect triggered by the user.
GenericDisconnect, //server disconnected, but no specific reason given.
Reconnecting, //client lost connection and is attempting to reconnect.
HostDisconnected, //Intentional Disconnect from the host
}

public enum OnlineMode
Expand Down Expand Up @@ -245,8 +247,6 @@ public void RequestDisconnect()
}
m_ClientPortal.OnUserDisconnectRequest();
m_ServerPortal.OnUserDisconnectRequest();
SessionManager<SessionPlayerData>.Instance.OnUserDisconnectRequest();
NetManager.Shutdown();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ public void OnClientSceneChanged(ulong clientId, int sceneIndex)
public void OnUserDisconnectRequest()
{
Clear();
if (m_Portal.NetManager.IsServer)
{
SendServerToAllClientsSetDisconnectReason(ConnectStatus.HostDisconnected);
// wait before shutting down to make sure those messages get sent before the clients disconnect.
StartCoroutine(WaitToShutdown());
}
}

IEnumerator WaitToShutdown()
{
yield return new WaitForSeconds(0.5f);
SessionManager<SessionPlayerData>.Instance.OnUserDisconnectRequest();
m_Portal.NetManager.Shutdown();
}

private void Clear()
Expand Down Expand Up @@ -230,6 +243,16 @@ public void SendServerToClientSetDisconnectReason(ulong clientID, ConnectStatus
writer.WriteValueSafe(status);
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(nameof(ClientGameNetPortal.ReceiveServerToClientSetDisconnectReason_CustomMessage), clientID, writer);
}
/// <summary>
/// Sends a DisconnectReason to all connected clients. This should only be done on the server, prior to disconnecting the clients.
/// </summary>
/// <param name="status"> The reason for the upcoming disconnect.</param>
public void SendServerToAllClientsSetDisconnectReason(ConnectStatus status)
{
var writer = new FastBufferWriter(sizeof(ConnectStatus), Allocator.Temp);
writer.WriteValueSafe(status);
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(nameof(ClientGameNetPortal.ReceiveServerToClientSetDisconnectReason_CustomMessage), writer);
}

/// <summary>
/// Responsible for the Server->Client custom message of the connection result.
Expand Down