Skip to content

Commit e2a0fb6

Browse files
fix: disconnect issue with wifi turned off (#562)
Disconnecting wifi caused an issue where clients wouldn't be able to reconnect. This is due to a bug in NGO's Shutdown, which happens when it's called when NGO isn't Listening. This PR adds a check around each Shutdown to make sure we're listing before calling it. --> workaround This PR also cleans up our disconnect handling, to make sure we're using the same connection flow each time. --> cherrypick This also fixes an issue where we didn't sent the appropriate allocation Id to lobby. --> cherrypick
1 parent 0d8d44a commit e2a0fb6

File tree

9 files changed

+77
-68
lines changed

9 files changed

+77
-68
lines changed

Assets/BossRoom/Prefabs/NetworkingManager.prefab

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,15 @@ MonoBehaviour:
5050
m_HeartbeatTimeoutMS: 500
5151
m_ConnectTimeoutMS: 1000
5252
m_MaxConnectAttempts: 60
53-
m_DisconnectTimeoutMS: 10000
53+
m_DisconnectTimeoutMS: 5000
5454
ConnectionData:
5555
Address: 127.0.0.1
5656
Port: 7777
5757
ServerListenAddress:
58+
DebugSimulator:
59+
PacketDelayMS: 0
60+
PacketJitterMS: 0
61+
PacketDropRate: 0
5862
--- !u!1 &503411707
5963
GameObject:
6064
m_ObjectHideFlags: 0
@@ -105,11 +109,15 @@ MonoBehaviour:
105109
m_HeartbeatTimeoutMS: 500
106110
m_ConnectTimeoutMS: 1000
107111
m_MaxConnectAttempts: 60
108-
m_DisconnectTimeoutMS: 10000
112+
m_DisconnectTimeoutMS: 5000
109113
ConnectionData:
110114
Address: 127.0.0.1
111115
Port: 7777
112116
ServerListenAddress:
117+
DebugSimulator:
118+
PacketDelayMS: 0
119+
PacketJitterMS: 0
120+
PacketDropRate: 0
113121
--- !u!1 &5436007408952557947
114122
GameObject:
115123
m_ObjectHideFlags: 0
@@ -219,7 +227,7 @@ MonoBehaviour:
219227
SourceHashToOverride: 0
220228
OverridingTargetPrefab: {fileID: 0}
221229
TickRate: 30
222-
ClientConnectionBufferTimeout: 10
230+
ClientConnectionBufferTimeout: 5
223231
ConnectionApproval: 1
224232
ConnectionData:
225233
EnableTimeResync: 0

Assets/BossRoom/Scripts/Client/UI/Lobby/LobbyUIMediator.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class LobbyUIMediator : MonoBehaviour
2929
NameGenerationData m_NameGenerationData;
3030
GameNetPortal m_GameNetPortal;
3131
ClientGameNetPortal m_ClientNetPortal;
32+
IDisposable m_Subscriptions;
3233

3334
const string k_DefaultLobbyName = "no-name";
3435

@@ -39,6 +40,7 @@ void InjectDependenciesAndInitialize(
3940
LocalLobby localLobby,
4041
NameGenerationData nameGenerationData,
4142
GameNetPortal gameNetPortal,
43+
ISubscriber<ConnectStatus> connectStatusSub,
4244
ClientGameNetPortal clientGameNetPortal
4345
)
4446
{
@@ -51,17 +53,22 @@ ClientGameNetPortal clientGameNetPortal
5153

5254
RegenerateName();
5355

54-
m_ClientNetPortal.NetworkTimedOut += OnNetworkTimeout;
56+
m_Subscriptions = connectStatusSub.Subscribe(OnConnectStatus);
5557
}
5658

57-
void OnDestroy()
59+
void OnConnectStatus(ConnectStatus status)
5860
{
59-
if (m_ClientNetPortal != null)
61+
if (status == ConnectStatus.GenericDisconnect)
6062
{
61-
m_ClientNetPortal.NetworkTimedOut -= OnNetworkTimeout;
63+
UnblockUIAfterLoadingIsComplete();
6264
}
6365
}
6466

67+
void OnDestroy()
68+
{
69+
m_Subscriptions?.Dispose();
70+
}
71+
6572
//Lobby and Relay calls done from UI
6673

6774
public void CreateLobbyRequest(string lobbyName, bool isPrivate, int maxPlayers, OnlineMode onlineMode)
@@ -236,15 +243,5 @@ void UnblockUIAfterLoadingIsComplete()
236243
m_LoadingSpinner.SetActive(false);
237244
}
238245
}
239-
240-
/// <summary>
241-
/// Invoked when the client sent a connection request to the server and didn't hear back at all.
242-
/// This should create a UI letting the player know that something went wrong and to try again
243-
/// </summary>
244-
void OnNetworkTimeout()
245-
{
246-
m_LobbyServiceFacade.EndTracking();
247-
UnblockUIAfterLoadingIsComplete();
248-
}
249246
}
250247
}

Assets/BossRoom/Scripts/Client/UI/PostGameUI.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using UnityEngine.SceneManagement;
33
using UnityEngine.UI;
44
using TMPro;
5+
using Unity.Multiplayer.Samples.BossRoom.Client;
56
using Unity.Multiplayer.Samples.BossRoom.Shared;
67
using Unity.Multiplayer.Samples.BossRoom.Shared.Infrastructure;
78
using Unity.Multiplayer.Samples.Utilities;
@@ -102,7 +103,7 @@ public void OnPlayAgainClicked()
102103

103104
public void OnMainMenuClicked()
104105
{
105-
m_ApplicationController.LeaveSession();
106+
m_ApplicationController.LeaveSession(withReason: ConnectStatus.UserRequestedDisconnect);
106107
}
107108
}
108109
}

Assets/BossRoom/Scripts/Client/UI/UIQuitPanel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void Quit()
3535
}
3636
else
3737
{
38-
m_ApplicationController.LeaveSession();
38+
m_ApplicationController.LeaveSession(withReason: ConnectStatus.UserRequestedDisconnect);
3939
}
4040

4141
gameObject.SetActive(false);

Assets/BossRoom/Scripts/Shared/ApplicationController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,15 @@ private bool OnWantToQuit()
108108
return canQuit;
109109
}
110110

111-
public void LeaveSession()
111+
public void LeaveSession(ConnectStatus withReason = ConnectStatus.Undefined)
112112
{
113113
m_LobbyServiceFacade.ForceLeaveLobbyAttempt();
114114

115115
// first disconnect then return to menu
116116
var gameNetPortal = GameNetPortal.Instance;
117117
if (gameNetPortal != null)
118118
{
119-
gameNetPortal.RequestDisconnect();
119+
gameNetPortal.RequestDisconnect(withReason);
120120
}
121121

122122
SceneLoaderWrapper.Instance.LoadScene("MainMenu");

Assets/BossRoom/Scripts/Shared/Net/ConnectionManagement/ClientGameNetPortal.cs

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,8 @@ public class ClientGameNetPortal : MonoBehaviour
3131
/// <summary>
3232
/// Time in seconds before the client considers a lack of server response a timeout
3333
/// </summary>
34-
private const int k_TimeoutDuration = 10;
35-
const int k_NbReconnectAttempts = 1;
36-
37-
/// <summary>
38-
/// This event fires when the client sent out a request to start the client, but failed to hear back after an allotted amount of
39-
/// time from the host.
40-
/// </summary>
41-
public event Action NetworkTimedOut;
34+
private const int k_TimeoutDuration = 5;
35+
const int k_NbReconnectAttempts = 2;
4236

4337
ApplicationController m_ApplicationController;
4438
LobbyServiceFacade m_LobbyServiceFacade;
@@ -93,14 +87,15 @@ public void OnNetworkReady()
9387
}
9488
}
9589

96-
/// <summary>
97-
/// Invoked when the user has requested a disconnect via the UI, e.g. when hitting "Return to Main Menu" in the post-game scene.
98-
/// </summary>
99-
public void OnUserDisconnectRequest()
90+
public void OnDisconnectRequest(ConnectStatus withDisconnectReason = ConnectStatus.Undefined)
10091
{
10192
if (m_Portal.NetManager.IsClient)
10293
{
103-
DisconnectReason.SetDisconnectReason(ConnectStatus.UserRequestedDisconnect);
94+
if (withDisconnectReason != ConnectStatus.Undefined)
95+
{
96+
DisconnectReason.SetDisconnectReason(withDisconnectReason);
97+
}
98+
10499
if (m_TryToReconnectCoroutine != null)
105100
{
106101
StopCoroutine(m_TryToReconnectCoroutine);
@@ -116,7 +111,7 @@ public void OnUserDisconnectRequest()
116111
}
117112

118113
// only do it here if we are not the host. The host will do it in ServerGameNetPortal
119-
if (!m_Portal.NetManager.IsHost)
114+
if (!m_Portal.NetManager.IsHost && m_Portal.NetManager.IsListening)
120115
{
121116
m_Portal.NetManager.Shutdown();
122117
}
@@ -165,25 +160,26 @@ void OnDisconnectOrTimeout(ulong clientID)
165160

166161
//On a client disconnect we want to take them back to the main menu.
167162
//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;
168-
if (SceneManager.GetActiveScene().name != "MainMenu")
163+
switch (DisconnectReason.Reason)
169164
{
170-
if (DisconnectReason.Reason == ConnectStatus.UserRequestedDisconnect || DisconnectReason.Reason == ConnectStatus.HostDisconnected || NetworkManager.Singleton.IsHost)
171-
{
172-
// simply shut down and go back to main menu
173-
m_ApplicationController.LeaveSession();
174-
}
175-
else
176-
{
165+
case ConnectStatus.UserRequestedDisconnect:
166+
case ConnectStatus.HostDisconnected:
167+
case ConnectStatus.LoggedInAgain:
168+
case ConnectStatus.ServerFull:
169+
m_ApplicationController.LeaveSession(); // go through the normal leave flow
170+
break;
171+
case ConnectStatus.GenericDisconnect:
172+
case ConnectStatus.Undefined:
177173
DisconnectReason.SetDisconnectReason(ConnectStatus.Reconnecting);
174+
178175
// load new scene to workaround MTT-2684
179176
SceneManager.LoadScene("Loading");
177+
180178
// try reconnecting
181179
m_TryToReconnectCoroutine ??= StartCoroutine(TryToReconnect(lobbyCode));
182-
}
183-
}
184-
else
185-
{
186-
NetworkTimedOut?.Invoke();
180+
break;
181+
default:
182+
throw new NotImplementedException(DisconnectReason.Reason.ToString());
187183
}
188184

189185
m_ConnectStatusPub.Publish(DisconnectReason.Reason);
@@ -197,7 +193,11 @@ private IEnumerator TryToReconnect(string lobbyCode)
197193
int nbTries = 0;
198194
while (nbTries < k_NbReconnectAttempts)
199195
{
200-
NetworkManager.Singleton.Shutdown();
196+
if (NetworkManager.Singleton.IsListening)
197+
{
198+
NetworkManager.Singleton.Shutdown();
199+
}
200+
201201
yield return new WaitWhile(() => NetworkManager.Singleton.ShutdownInProgress); // wait until NetworkManager completes shutting down
202202
Debug.Log($"Reconnecting attempt {nbTries + 1}/{k_NbReconnectAttempts}...");
203203
if (!string.IsNullOrEmpty(lobbyCode))
@@ -223,7 +223,11 @@ private IEnumerator TryToReconnect(string lobbyCode)
223223
// If the coroutine has not been stopped before this, it means we failed to connect during all attempts
224224
Debug.Log("All tries failed, returning to main menu");
225225
m_LobbyServiceFacade.ForceLeaveLobbyAttempt();
226-
NetworkManager.Singleton.Shutdown();
226+
if (NetworkManager.Singleton.IsListening)
227+
{
228+
NetworkManager.Singleton.Shutdown();
229+
}
230+
227231
SceneLoaderWrapper.Instance.LoadScene("MainMenu");
228232
if (!DisconnectReason.HasTransitionReason)
229233
{
@@ -283,11 +287,9 @@ async void ConnectClient(Action<string> onFailure)
283287
{
284288
try
285289
{
286-
var clientRelayUtilityTask = UnityRelayUtilities.JoinRelayServerFromJoinCode(m_JoinCode);
287-
await clientRelayUtilityTask;
288-
var (ipv4Address, port, allocationIdBytes, connectionData, hostConnectionData, key) = clientRelayUtilityTask.Result;
290+
var (ipv4Address, port, allocationId, allocationIdBytes, connectionData, hostConnectionData, key) = await UnityRelayUtilities.JoinRelayServerFromJoinCode(m_JoinCode);
289291

290-
m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(allocationIdBytes.ToString(), m_JoinCode, null, null);
292+
m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(allocationId.ToString(), m_JoinCode, null, null);
291293
var utp = (UnityTransport)NetworkManager.Singleton.NetworkConfig.NetworkTransport;
292294
utp.SetRelayServerData(ipv4Address, port, allocationIdBytes, key, connectionData, hostConnectionData);
293295
}

Assets/BossRoom/Scripts/Shared/Net/ConnectionManagement/GameNetPortal.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,11 @@ public async void StartUnityRelayHost()
203203
// we now need to get the joinCode?
204204
var GDCRegion = "us-west2";
205205
// var GDCRegion = "us-east4";
206-
var serverRelayUtilityTask = UnityRelayUtilities.AllocateRelayServerAndGetJoinCode(k_MaxUnityRelayConnections, region: GDCRegion);
207-
await serverRelayUtilityTask;
208-
// we now have the info from the relay service
209-
var (ipv4Address, port, allocationIdBytes, connectionData, key, joinCode) = serverRelayUtilityTask.Result;
206+
var (ipv4Address, port, allocationId, allocationIdBytes, connectionData, key, joinCode) = await UnityRelayUtilities.AllocateRelayServerAndGetJoinCode(k_MaxUnityRelayConnections, region: GDCRegion);
210207

211208
m_LocalLobby.RelayJoinCode = joinCode;
212209
//next line enabled lobby and relay services integration
213-
m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(allocationIdBytes.ToString(), joinCode, null, null);
210+
m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(allocationId.ToString(), joinCode, null, null);
214211

215212
// we now need to set the RelayCode somewhere :P
216213
utp.SetRelayServerData(ipv4Address, port, allocationIdBytes, key, connectionData);
@@ -238,14 +235,14 @@ void StartHost()
238235
/// This will disconnect (on the client) or shutdown the server (on the host).
239236
/// It's a local signal (not from the network), indicating that the user has requested a disconnect.
240237
/// </summary>
241-
public void RequestDisconnect()
238+
public void RequestDisconnect(ConnectStatus withDisconnectReason = ConnectStatus.Undefined)
242239
{
243240
if (NetManager.IsServer)
244241
{
245242
NetManager.SceneManager.OnSceneEvent -= OnSceneEvent;
246243
}
247-
m_ClientPortal.OnUserDisconnectRequest();
248-
m_ServerPortal.OnUserDisconnectRequest();
244+
m_ClientPortal.OnDisconnectRequest(withDisconnectReason);
245+
m_ServerPortal.OnDisconnectRequest();
249246
}
250247

251248
public string GetPlayerId()

Assets/BossRoom/Scripts/Shared/Net/ConnectionManagement/ServerGameNetPortal.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ public void OnClientSceneChanged(ulong clientId, int sceneIndex)
127127
/// Handles the flow when a user has requested a disconnect via UI (which can be invoked on the Host, and thus must be
128128
/// handled in server code).
129129
/// </summary>
130-
public void OnUserDisconnectRequest()
130+
public void OnDisconnectRequest()
131131
{
132132
Clear();
133133
if (m_Portal.NetManager.IsServer)
@@ -145,7 +145,11 @@ IEnumerator WaitToShutdown()
145145
yield return null; // todo still needed? wait for UTP's update for it to send it's batched messages
146146
yield return null;
147147
SessionManager<SessionPlayerData>.Instance.OnUserDisconnectRequest();
148-
m_Portal.NetManager.Shutdown();
148+
if (m_Portal.NetManager.IsListening)
149+
{
150+
m_Portal.NetManager.Shutdown();
151+
}
152+
149153
SceneLoaderWrapper.Instance.IsClosingClients = false;
150154
}
151155

Packages/com.unity.multiplayer.samples.coop/Utilities/Net/UnityRelayUtilities.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public static class UnityRelayUtilities
1010
{
1111

1212
public static async
13-
Task<(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] connectionData, byte[] key, string
13+
Task<(string ipv4address, ushort port, Guid allocationId, byte[] allocationIdBytes, byte[] connectionData, byte[] key, string
1414
joinCode)> AllocateRelayServerAndGetJoinCode(int maxConnections, string region = null)
1515
{
1616
Allocation allocation;
@@ -37,12 +37,12 @@ public static async
3737
throw new Exception($"Creating join code request has failed: \n {exception.Message}");
3838
}
3939

40-
return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes,
40+
return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationId, allocation.AllocationIdBytes,
4141
allocation.ConnectionData, allocation.Key, joinCode);
4242
}
4343

4444
public static async
45-
Task<(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] connectionData, byte[]
45+
Task<(string ipv4address, ushort port, Guid allocationId, byte[] allocationIdBytes, byte[] connectionData, byte[]
4646
hostConnectionData, byte[] key)> JoinRelayServerFromJoinCode(string joinCode)
4747
{
4848
JoinAllocation allocation;
@@ -59,7 +59,7 @@ public static async
5959
Debug.Log($"host: {allocation.HostConnectionData[0]} {allocation.HostConnectionData[1]}");
6060
Debug.Log($"client: {allocation.AllocationId}");
6161

62-
return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes,
62+
return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationId, allocation.AllocationIdBytes,
6363
allocation.ConnectionData, allocation.HostConnectionData, allocation.Key);
6464
}
6565
}

0 commit comments

Comments
 (0)