Skip to content

Commit 06f66c1

Browse files
SamuelBellomonetcode-ci-serviceLPLafontaineB
authored
feat: bumping boss room to 1.1 (#708)
* After this PR Unity-Technologies/com.unity.netcode.gameobjects#2081 reverting MaxPayloadSize to default * basis works, still need to debug issue with client reconnecting a second time * setting back max payload size to default value. With recent changes, this now only applies to unreliable messages. With how little NGO uses unreliable messages, this shouldn't need any tweaking anymore. reserializing NetworkingManager, this removes the old max send queue size value as well. * Increasing connection approval timeout to 5 seconds, as 1 second was pretty short for a connection. If there's any packet drops or temporary lag spike, this could timeout the connection when it was actually fine. Still lower than the default 10 seconds. * using classes instead of structs now that we have managed types available in netvars * fixing null ref when doing reconnection flow * deprecated note for utilities * updating manifest and dependencies with 1.1.0 now it's released * initializing number of reconnect attempts before starting the reconnect coroutine * fixing player prefab being destroyed issue Co-authored-by: Unity Netcode CI <[email protected]> Co-authored-by: LPLafontaineB <[email protected]>
1 parent e63f6e2 commit 06f66c1

20 files changed

+270
-137
lines changed

Assets/Prefabs/NetworkingManager.prefab

+2-3
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ MonoBehaviour:
108108
SourceHashToOverride: 0
109109
OverridingTargetPrefab: {fileID: 0}
110110
TickRate: 30
111-
ClientConnectionBufferTimeout: 1
111+
ClientConnectionBufferTimeout: 5
112112
ConnectionApproval: 1
113113
ConnectionData:
114114
EnableTimeResync: 0
@@ -136,8 +136,7 @@ MonoBehaviour:
136136
m_EditorClassIdentifier:
137137
m_ProtocolType: 0
138138
m_MaxPacketQueueSize: 512
139-
m_MaxPayloadSize: 32000
140-
m_MaxSendQueueSize: 50000000
139+
m_MaxPayloadSize: 6144
141140
m_HeartbeatTimeoutMS: 500
142141
m_ConnectTimeoutMS: 1000
143142
m_MaxConnectAttempts: 10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
using Unity.BossRoom.UnityServices.Lobbies;
4+
using Unity.BossRoom.Utils;
5+
using Unity.Netcode.Transports.UTP;
6+
using Unity.Networking.Transport.Relay;
7+
using Unity.Services.Authentication;
8+
using Unity.Services.Core;
9+
using Unity.Services.Relay;
10+
using Unity.Services.Relay.Models;
11+
using UnityEngine;
12+
13+
namespace Unity.BossRoom.ConnectionManagement
14+
{
15+
/// <summary>
16+
/// ConnectionMethod contains all setup needed to setup NGO to be ready to start a connection, either host or client side.
17+
/// Please override this abstract class to add a new transport or way of connecting.
18+
/// </summary>
19+
public abstract class ConnectionMethodBase
20+
{
21+
protected ConnectionManager m_ConnectionManager;
22+
readonly ProfileManager m_ProfileManager;
23+
protected readonly string m_PlayerName;
24+
25+
public abstract Task SetupHostConnectionAsync();
26+
27+
public abstract Task SetupClientConnectionAsync();
28+
29+
public ConnectionMethodBase(ConnectionManager connectionManager, ProfileManager profileManager, string playerName)
30+
{
31+
m_ConnectionManager = connectionManager;
32+
m_ProfileManager = profileManager;
33+
m_PlayerName = playerName;
34+
}
35+
36+
protected void SetConnectionPayload(string playerId, string playerName)
37+
{
38+
var payload = JsonUtility.ToJson(new ConnectionPayload()
39+
{
40+
playerId = playerId,
41+
playerName = playerName,
42+
isDebug = Debug.isDebugBuild
43+
});
44+
45+
var payloadBytes = System.Text.Encoding.UTF8.GetBytes(payload);
46+
47+
m_ConnectionManager.NetworkManager.NetworkConfig.ConnectionData = payloadBytes;
48+
}
49+
50+
protected string GetPlayerId()
51+
{
52+
if (Services.Core.UnityServices.State != ServicesInitializationState.Initialized)
53+
{
54+
return ClientPrefs.GetGuid() + m_ProfileManager.Profile;
55+
}
56+
57+
return AuthenticationService.Instance.IsSignedIn ? AuthenticationService.Instance.PlayerId : ClientPrefs.GetGuid() + m_ProfileManager.Profile;
58+
}
59+
}
60+
61+
/// <summary>
62+
/// Simple IP connection setup with UTP
63+
/// </summary>
64+
class ConnectionMethodIP : ConnectionMethodBase
65+
{
66+
string m_Ipaddress;
67+
ushort m_Port;
68+
69+
public ConnectionMethodIP(string ip, ushort port, ConnectionManager connectionManager, ProfileManager profileManager, string playerName)
70+
: base(connectionManager, profileManager, playerName)
71+
{
72+
m_Ipaddress = ip;
73+
m_Port = port;
74+
m_ConnectionManager = connectionManager;
75+
}
76+
77+
public override async Task SetupClientConnectionAsync()
78+
{
79+
SetConnectionPayload(GetPlayerId(), m_PlayerName);
80+
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
81+
utp.SetConnectionData(m_Ipaddress, m_Port);
82+
}
83+
84+
public override async Task SetupHostConnectionAsync()
85+
{
86+
SetConnectionPayload(GetPlayerId(), m_PlayerName); // Need to set connection payload for host as well, as host is a client too
87+
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
88+
utp.SetConnectionData(m_Ipaddress, m_Port);
89+
}
90+
}
91+
92+
/// <summary>
93+
/// UTP's Relay connection setup
94+
/// </summary>
95+
class ConnectionMethodRelay : ConnectionMethodBase
96+
{
97+
LobbyServiceFacade m_LobbyServiceFacade;
98+
LocalLobby m_LocalLobby;
99+
100+
public ConnectionMethodRelay(LobbyServiceFacade lobbyServiceFacade, LocalLobby localLobby, ConnectionManager connectionManager, ProfileManager profileManager, string playerName)
101+
: base(connectionManager, profileManager, playerName)
102+
{
103+
m_LobbyServiceFacade = lobbyServiceFacade;
104+
m_LocalLobby = localLobby;
105+
m_ConnectionManager = connectionManager;
106+
}
107+
108+
public override async Task SetupClientConnectionAsync()
109+
{
110+
Debug.Log("Setting up Unity Relay client");
111+
112+
SetConnectionPayload(GetPlayerId(), m_PlayerName);
113+
114+
if (m_LobbyServiceFacade.CurrentUnityLobby == null)
115+
{
116+
throw new Exception("Trying to start relay while Lobby isn't set");
117+
}
118+
119+
Debug.Log($"Setting Unity Relay client with join code {m_LocalLobby.RelayJoinCode}");
120+
121+
// Create client joining allocation from join code
122+
var joinedAllocation = await RelayService.Instance.JoinAllocationAsync(m_LocalLobby.RelayJoinCode);
123+
Debug.Log($"client: {joinedAllocation.ConnectionData[0]} {joinedAllocation.ConnectionData[1]}, " +
124+
$"host: {joinedAllocation.HostConnectionData[0]} {joinedAllocation.HostConnectionData[1]}, " +
125+
$"client: {joinedAllocation.AllocationId}");
126+
127+
await m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(joinedAllocation.AllocationId.ToString(), m_LocalLobby.RelayJoinCode);
128+
129+
// Configure UTP with allocation
130+
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
131+
utp.SetRelayServerData(new RelayServerData(joinedAllocation, OnlineState.k_DtlsConnType));
132+
}
133+
134+
public override async Task SetupHostConnectionAsync()
135+
{
136+
Debug.Log("Setting up Unity Relay host");
137+
138+
SetConnectionPayload(GetPlayerId(), m_PlayerName); // Need to set connection payload for host as well, as host is a client too
139+
140+
// Create relay allocation
141+
Allocation hostAllocation = await RelayService.Instance.CreateAllocationAsync(m_ConnectionManager.MaxConnectedPlayers, region: null);
142+
var joinCode = await RelayService.Instance.GetJoinCodeAsync(hostAllocation.AllocationId);
143+
144+
Debug.Log($"server: connection data: {hostAllocation.ConnectionData[0]} {hostAllocation.ConnectionData[1]}, " +
145+
$"allocation ID:{hostAllocation.AllocationId}, region:{hostAllocation.Region}");
146+
147+
m_LocalLobby.RelayJoinCode = joinCode;
148+
149+
//next line enable lobby and relay services integration
150+
await m_LobbyServiceFacade.UpdateLobbyDataAsync(m_LocalLobby.GetDataForUnityServices());
151+
await m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(hostAllocation.AllocationIdBytes.ToString(), joinCode);
152+
153+
// Setup UTP with relay connection info
154+
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
155+
utp.SetRelayServerData(new RelayServerData(hostAllocation, OnlineState.k_DtlsConnType)); // This is with DTLS enabled for a secure connection
156+
}
157+
}
158+
}

Assets/Scripts/ConnectionManagement/ConnectionMethod.cs.meta

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
22
using System.Threading.Tasks;
33
using Unity.BossRoom.UnityServices.Lobbies;
4-
using Unity.Multiplayer.Samples.BossRoom;
54
using Unity.Multiplayer.Samples.Utilities;
6-
using Unity.Netcode.Transports.UTP;
75
using UnityEngine;
86
using VContainer;
97

@@ -20,6 +18,13 @@ class ClientConnectingState : OnlineState
2018
protected LobbyServiceFacade m_LobbyServiceFacade;
2119
[Inject]
2220
protected LocalLobby m_LocalLobby;
21+
ConnectionMethodBase m_ConnectionMethod;
22+
23+
public ClientConnectingState Configure(ConnectionMethodBase baseConnectionMethod)
24+
{
25+
m_ConnectionMethod = baseConnectionMethod;
26+
return this;
27+
}
2328

2429
public override void Enter()
2530
{
@@ -37,6 +42,12 @@ public override void OnClientConnected(ulong _)
3742
}
3843

3944
public override void OnClientDisconnect(ulong _)
45+
{
46+
// client ID is for sure ours here
47+
StartingClientFailedAsync();
48+
}
49+
50+
protected void StartingClientFailedAsync()
4051
{
4152
m_ConnectStatusPublisher.Publish(ConnectStatus.StartClientFailed);
4253
m_ConnectionManager.ChangeState(m_ConnectionManager.m_Offline);
@@ -48,52 +59,30 @@ public override void OnDisconnectReasonReceived(ConnectStatus disconnectReason)
4859
m_ConnectionManager.ChangeState(m_ConnectionManager.m_DisconnectingWithReason);
4960
}
5061

51-
protected async Task ConnectClientAsync()
62+
63+
internal async Task ConnectClientAsync()
5264
{
53-
bool success = true;
54-
if (m_LobbyServiceFacade.CurrentUnityLobby != null)
65+
try
5566
{
56-
success = await JoinRelayServerAsync();
57-
}
67+
// Setup NGO with current connection method
68+
await m_ConnectionMethod.SetupClientConnectionAsync();
5869

59-
if (success)
60-
{
61-
success = m_ConnectionManager.NetworkManager.StartClient();
62-
}
70+
// NGO's StartClient launches everything
71+
if (!m_ConnectionManager.NetworkManager.StartClient())
72+
{
73+
throw new Exception("NetworkManager StartClient failed");
74+
}
6375

64-
if (success)
65-
{
6676
SceneLoaderWrapper.Instance.AddOnSceneEventCallback();
6777
m_ConnectionManager.RegisterCustomMessages();
6878
}
69-
else
70-
{
71-
OnClientDisconnect(0);
72-
}
73-
}
74-
75-
async Task<bool> JoinRelayServerAsync()
76-
{
77-
Debug.Log($"Setting Unity Relay client with join code {m_LocalLobby.RelayJoinCode}");
78-
79-
try
80-
{
81-
var (ipv4Address, port, allocationIdBytes, allocationId, connectionData, hostConnectionData, key) =
82-
await UnityRelayUtilities.JoinRelayServerFromJoinCode(m_LocalLobby.RelayJoinCode);
83-
84-
await m_LobbyServiceFacade.UpdatePlayerRelayInfoAsync(allocationId.ToString(), m_LocalLobby.RelayJoinCode);
85-
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
86-
utp.SetClientRelayData(ipv4Address, port, allocationIdBytes, key, connectionData, hostConnectionData, isSecure: true);
87-
}
8879
catch (Exception e)
8980
{
90-
Debug.Log($"Relay join failed: {e.Message}");
91-
//leave the lobby if relay failed for some reason
92-
await m_LobbyServiceFacade.EndTracking();
93-
return false;
81+
Debug.LogError("Error connecting client, see following exception");
82+
Debug.LogException(e);
83+
StartingClientFailedAsync();
84+
throw;
9485
}
95-
96-
return true;
9786
}
9887
}
9988
}

Assets/Scripts/ConnectionManagement/ConnectionState/ClientReconnectingState.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ class ClientReconnectingState : ClientConnectingState
2525

2626
public override void Enter()
2727
{
28+
m_NbAttempts = 0;
2829
m_LobbyCode = m_LobbyServiceFacade.CurrentUnityLobby != null ? m_LobbyServiceFacade.CurrentUnityLobby.LobbyCode : "";
2930
m_ReconnectCoroutine = m_ConnectionManager.StartCoroutine(ReconnectCoroutine());
30-
m_NbAttempts = 0;
3131
}
3232

3333
public override void Exit()

Assets/Scripts/ConnectionManagement/ConnectionState/OfflineState.cs

+12-40
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
using Unity.BossRoom.UnityServices.Lobbies;
44
using Unity.BossRoom.Utils;
55
using Unity.Multiplayer.Samples.Utilities;
6-
using Unity.Netcode.Transports.UTP;
7-
using Unity.Services.Authentication;
8-
using Unity.Services.Core;
96
using UnityEngine;
107
using UnityEngine.SceneManagement;
118
using VContainer;
@@ -22,6 +19,8 @@ class OfflineState : ConnectionState
2219
LobbyServiceFacade m_LobbyServiceFacade;
2320
[Inject]
2421
ProfileManager m_ProfileManager;
22+
[Inject]
23+
LocalLobby m_LocalLobby;
2524

2625
const string k_MainMenuSceneName = "MainMenu";
2726

@@ -39,55 +38,28 @@ public override void Exit() { }
3938

4039
public override void StartClientIP(string playerName, string ipaddress, int port)
4140
{
42-
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
43-
utp.SetConnectionData(ipaddress, (ushort)port);
44-
SetConnectionPayload(GetPlayerId(), playerName);
45-
m_ConnectionManager.ChangeState(m_ConnectionManager.m_ClientConnecting);
41+
var connectionMethod = new ConnectionMethodIP(ipaddress, (ushort)port, m_ConnectionManager, m_ProfileManager, playerName);
42+
m_ConnectionManager.m_ClientReconnecting.Configure(connectionMethod);
43+
m_ConnectionManager.ChangeState(m_ConnectionManager.m_ClientConnecting.Configure(connectionMethod));
4644
}
4745

4846
public override void StartClientLobby(string playerName)
4947
{
50-
SetConnectionPayload(GetPlayerId(), playerName);
51-
m_ConnectionManager.ChangeState(m_ConnectionManager.m_ClientConnecting);
48+
var connectionMethod = new ConnectionMethodRelay(m_LobbyServiceFacade, m_LocalLobby, m_ConnectionManager, m_ProfileManager, playerName);
49+
m_ConnectionManager.m_ClientReconnecting.Configure(connectionMethod);
50+
m_ConnectionManager.ChangeState(m_ConnectionManager.m_ClientConnecting.Configure(connectionMethod));
5251
}
5352

5453
public override void StartHostIP(string playerName, string ipaddress, int port)
5554
{
56-
var utp = (UnityTransport)m_ConnectionManager.NetworkManager.NetworkConfig.NetworkTransport;
57-
utp.SetConnectionData(ipaddress, (ushort)port);
58-
59-
SetConnectionPayload(GetPlayerId(), playerName);
60-
m_ConnectionManager.ChangeState(m_ConnectionManager.m_StartingHost);
55+
var connectionMethod = new ConnectionMethodIP(ipaddress, (ushort)port, m_ConnectionManager, m_ProfileManager, playerName);
56+
m_ConnectionManager.ChangeState(m_ConnectionManager.m_StartingHost.Configure(connectionMethod));
6157
}
6258

6359
public override void StartHostLobby(string playerName)
6460
{
65-
SetConnectionPayload(GetPlayerId(), playerName);
66-
m_ConnectionManager.ChangeState(m_ConnectionManager.m_StartingHost);
67-
}
68-
69-
void SetConnectionPayload(string playerId, string playerName)
70-
{
71-
var payload = JsonUtility.ToJson(new ConnectionPayload()
72-
{
73-
playerId = playerId,
74-
playerName = playerName,
75-
isDebug = Debug.isDebugBuild
76-
});
77-
78-
var payloadBytes = System.Text.Encoding.UTF8.GetBytes(payload);
79-
80-
m_ConnectionManager.NetworkManager.NetworkConfig.ConnectionData = payloadBytes;
81-
}
82-
83-
string GetPlayerId()
84-
{
85-
if (UnityServices.State != ServicesInitializationState.Initialized)
86-
{
87-
return ClientPrefs.GetGuid() + m_ProfileManager.Profile;
88-
}
89-
90-
return AuthenticationService.Instance.IsSignedIn ? AuthenticationService.Instance.PlayerId : ClientPrefs.GetGuid() + m_ProfileManager.Profile;
61+
var connectionMethod = new ConnectionMethodRelay(m_LobbyServiceFacade, m_LocalLobby, m_ConnectionManager, m_ProfileManager, playerName);
62+
m_ConnectionManager.ChangeState(m_ConnectionManager.m_StartingHost.Configure(connectionMethod));
9163
}
9264
}
9365
}

Assets/Scripts/ConnectionManagement/ConnectionState/OnlineState.cs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Unity.BossRoom.ConnectionManagement
55
/// </summary>
66
abstract class OnlineState : ConnectionState
77
{
8+
public const string k_DtlsConnType = "dtls";
89

910
public override void OnUserRequestedShutdown()
1011
{

0 commit comments

Comments
 (0)