Skip to content

Commit db90813

Browse files
feat: simplifying reconnection (#804)
* Simplifying reconnection * Adding possibility of early failure when reconnecting if lobby no longer exists
1 parent 2428bd8 commit db90813

File tree

6 files changed

+73
-40
lines changed

6 files changed

+73
-40
lines changed

.yamato/mobile-build-and-run.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Build_Player_With_Tests_iOS_{{ project.name }}_{{ editor }}:
1313
flavor: b1.large
1414

1515
commands:
16-
- pip install unity-downloader-cli --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
16+
- pip install unity-downloader-cli==1.2.0 --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
1717
- unity-downloader-cli -c Editor -c iOS -u {{ editor }} --fast --wait
1818
- curl -s https://artifactory.prd.it.unity3d.com/artifactory/unity-tools-local/utr-standalone/utr --output utr
1919
- chmod +x ./utr
@@ -42,7 +42,7 @@ Build_Player_With_Tests_Android_{{ project.name }}_{{ editor }}:
4242

4343
commands:
4444
# Download unity-downloader-cli
45-
- pip install unity-downloader-cli --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
45+
- pip install unity-downloader-cli==1.2.0 --index-url https://artifactory.prd.it.unity3d.com/artifactory/api/pypi/pypi/simple --upgrade
4646
- curl -s https://artifactory.prd.it.unity3d.com/artifactory/unity-tools/utr-standalone/utr.bat --output utr.bat
4747
- python .yamato/disable-burst-if-requested.py --project-path {{ project.path }} --platform Android
4848
- unity-downloader-cli -c Editor -c Android -u {{ editor }} --fast --wait

Assets/Scripts/ConnectionManagement/ConnectionManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using Unity.BossRoom.Utils;
4-
using Unity.Collections;
54
using Unity.Netcode;
65
using UnityEngine;
76
using UUnity.BossRoom.ConnectionManagement;

Assets/Scripts/ConnectionManagement/ConnectionMethod.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,28 @@ public abstract class ConnectionMethodBase
2323
protected readonly string m_PlayerName;
2424
protected const string k_DtlsConnType = "dtls";
2525

26+
/// <summary>
27+
/// Setup the host connection prior to starting the NetworkManager
28+
/// </summary>
29+
/// <returns></returns>
2630
public abstract Task SetupHostConnectionAsync();
2731

32+
33+
/// <summary>
34+
/// Setup the client connection prior to starting the NetworkManager
35+
/// </summary>
36+
/// <returns></returns>
2837
public abstract Task SetupClientConnectionAsync();
2938

39+
/// <summary>
40+
/// Setup the client for reconnection prior to reconnecting
41+
/// </summary>
42+
/// <returns>
43+
/// success = true if succeeded in setting up reconnection, false if failed.
44+
/// shouldTryAgain = true if we should try again after failing, false if not.
45+
/// </returns>
46+
public abstract Task<(bool success, bool shouldTryAgain)> SetupClientReconnectionAsync();
47+
3048
public ConnectionMethodBase(ConnectionManager connectionManager, ProfileManager profileManager, string playerName)
3149
{
3250
m_ConnectionManager = connectionManager;
@@ -82,6 +100,12 @@ public override async Task SetupClientConnectionAsync()
82100
utp.SetConnectionData(m_Ipaddress, m_Port);
83101
}
84102

103+
public override async Task<(bool success, bool shouldTryAgain)> SetupClientReconnectionAsync()
104+
{
105+
// Nothing to do here
106+
return (true, true);
107+
}
108+
85109
public override async Task SetupHostConnectionAsync()
86110
{
87111
SetConnectionPayload(GetPlayerId(), m_PlayerName); // Need to set connection payload for host as well, as host is a client too
@@ -91,7 +115,7 @@ public override async Task SetupHostConnectionAsync()
91115
}
92116

93117
/// <summary>
94-
/// UTP's Relay connection setup
118+
/// UTP's Relay connection setup using the Lobby integration
95119
/// </summary>
96120
class ConnectionMethodRelay : ConnectionMethodBase
97121
{
@@ -132,6 +156,32 @@ public override async Task SetupClientConnectionAsync()
132156
utp.SetRelayServerData(new RelayServerData(joinedAllocation, k_DtlsConnType));
133157
}
134158

159+
public override async Task<(bool success, bool shouldTryAgain)> SetupClientReconnectionAsync()
160+
{
161+
if (m_LobbyServiceFacade.CurrentUnityLobby == null)
162+
{
163+
Debug.Log("Lobby does not exist anymore, stopping reconnection attempts.");
164+
return (false, false);
165+
}
166+
167+
// When using Lobby with Relay, if a user is disconnected from the Relay server, the server will notify the
168+
// Lobby service and mark the user as disconnected, but will not remove them from the lobby. They then have
169+
// some time to attempt to reconnect (defined by the "Disconnect removal time" parameter on the dashboard),
170+
// after which they will be removed from the lobby completely.
171+
// See https://docs.unity.com/lobby/reconnect-to-lobby.html
172+
var lobby = await m_LobbyServiceFacade.ReconnectToLobbyAsync(m_LocalLobby.LobbyID);
173+
var success = lobby != null;
174+
if (success)
175+
{
176+
Debug.Log("Successfully reconnected to Lobby.");
177+
}
178+
else
179+
{
180+
Debug.Log("Failed to reconnect to Lobby.");
181+
}
182+
return (success, true); // return a success if reconnecting to lobby returns a lobby
183+
}
184+
135185
public override async Task SetupHostConnectionAsync()
136186
{
137187
Debug.Log("Setting up Unity Relay host");

Assets/Scripts/ConnectionManagement/ConnectionState/ClientConnectingState.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
3-
using Unity.BossRoom.UnityServices.Lobbies;
43
using Unity.Multiplayer.Samples.Utilities;
54
using UnityEngine;
6-
using VContainer;
75

86
namespace Unity.BossRoom.ConnectionManagement
97
{
@@ -13,11 +11,7 @@ namespace Unity.BossRoom.ConnectionManagement
1311
/// </summary>
1412
class ClientConnectingState : OnlineState
1513
{
16-
[Inject]
17-
protected LobbyServiceFacade m_LobbyServiceFacade;
18-
[Inject]
19-
protected LocalLobby m_LocalLobby;
20-
ConnectionMethodBase m_ConnectionMethod;
14+
protected ConnectionMethodBase m_ConnectionMethod;
2115

2216
public ClientConnectingState Configure(ConnectionMethodBase baseConnectionMethod)
2317
{

Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@ class ClientReconnectingState : ClientConnectingState
1919
IPublisher<ReconnectMessage> m_ReconnectMessagePublisher;
2020

2121
Coroutine m_ReconnectCoroutine;
22-
string m_LobbyCode = "";
2322
int m_NbAttempts;
2423

2524
const float k_TimeBetweenAttempts = 5;
2625

2726
public override void Enter()
2827
{
2928
m_NbAttempts = 0;
30-
m_LobbyCode = m_LobbyServiceFacade.CurrentUnityLobby != null ? m_LobbyServiceFacade.CurrentUnityLobby.LobbyCode : "";
3129
m_ReconnectCoroutine = m_ConnectionManager.StartCoroutine(ReconnectCoroutine());
3230
}
3331

@@ -108,36 +106,25 @@ IEnumerator ReconnectCoroutine()
108106
Debug.Log($"Reconnecting attempt {m_NbAttempts + 1}/{m_ConnectionManager.NbReconnectAttempts}...");
109107
m_ReconnectMessagePublisher.Publish(new ReconnectMessage(m_NbAttempts, m_ConnectionManager.NbReconnectAttempts));
110108
m_NbAttempts++;
111-
if (!string.IsNullOrEmpty(m_LobbyCode)) // Attempting to reconnect to lobby.
112-
{
113-
// When using Lobby with Relay, if a user is disconnected from the Relay server, the server will notify
114-
// the Lobby service and mark the user as disconnected, but will not remove them from the lobby. They
115-
// then have some time to attempt to reconnect (defined by the "Disconnect removal time" parameter on
116-
// the dashboard), after which they will be removed from the lobby completely.
117-
// See https://docs.unity.com/lobby/reconnect-to-lobby.html
118-
var reconnectingToLobby = m_LobbyServiceFacade.ReconnectToLobbyAsync(m_LocalLobby?.LobbyID);
119-
yield return new WaitUntil(() => reconnectingToLobby.IsCompleted);
109+
var reconnectingSetupTask = m_ConnectionMethod.SetupClientReconnectionAsync();
110+
yield return new WaitUntil(() => reconnectingSetupTask.IsCompleted);
120111

121-
// If succeeded, attempt to connect to Relay
122-
if (!reconnectingToLobby.IsFaulted && reconnectingToLobby.Result != null)
123-
{
124-
// If this fails, the OnClientDisconnect callback will be invoked by Netcode
125-
var connectingToRelay = ConnectClientAsync();
126-
yield return new WaitUntil(() => connectingToRelay.IsCompleted);
127-
}
128-
else
129-
{
130-
Debug.Log("Failed reconnecting to lobby.");
131-
// Calling OnClientDisconnect to mark this attempt as failed and either start a new one or give up
132-
// and return to the Offline state
133-
OnClientDisconnect(0);
134-
}
135-
}
136-
else // If not using Lobby, simply try to reconnect to the server directly
112+
if (!reconnectingSetupTask.IsFaulted && reconnectingSetupTask.Result.success)
137113
{
138114
// If this fails, the OnClientDisconnect callback will be invoked by Netcode
139-
var connectingClient = ConnectClientAsync();
140-
yield return new WaitUntil(() => connectingClient.IsCompleted);
115+
var connectingToRelay = ConnectClientAsync();
116+
yield return new WaitUntil(() => connectingToRelay.IsCompleted);
117+
}
118+
else
119+
{
120+
if (!reconnectingSetupTask.Result.shouldTryAgain)
121+
{
122+
// setting number of attempts to max so no new attempts are made
123+
m_NbAttempts = m_ConnectionManager.NbReconnectAttempts;
124+
}
125+
// Calling OnClientDisconnect to mark this attempt as failed and either start a new one or give up
126+
// and return to the Offline state
127+
OnClientDisconnect(0);
141128
}
142129
}
143130
}

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ Additional documentation and release notes are available at [Multiplayer Documen
1111
* Clarified a TODO comment inside ClientCharacter, detailing how anticipation should only be executed on owning client players (#786)
1212
* Removed now unnecessary cached NetworkBehaviour status on some components, since they now do not allocate memory (#799)
1313

14+
### Changed
15+
* Simplified reconnection flow by offloading responsibility to ConnectionMethod (#804). Now the ClientReconnectingState uses the ConnectionMethod it is configured with to handle setting up reconnection (i.e. reconnecting to the Lobby before trying to reconnect to the Relay server if it is using Relay and Lobby). It can now also fail early and stop retrying if the lobby doesn't exist anymore.
16+
1417
### Fixed
1518
* EnemyPortals' VFX get disabled and re-enabled once the breakable crystals are broken (#784)
1619
* Elements inside the Tank's and Rogue's AnimatorTriggeredSpecialFX list have been revised to not loop AudioSource clips, ending the logging of multiple warnings to the console (#785)

0 commit comments

Comments
 (0)