From e02cad15e29f74c71c280d9c94bd03f0b1bd3e8c Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Tue, 15 Jul 2025 20:54:17 -0500 Subject: [PATCH 01/19] update This update is a work in progress resolution to the issue where disconnect event notifications were too vague and did not provide any way to know what the cause of the disconnect was. --- .../Connection/NetworkConnectionManager.cs | 65 ++++++++++++---- .../Runtime/Core/NetworkManager.cs | 14 +++- .../Runtime/Transports/NetworkTransport.cs | 74 +++++++++++++++++++ .../Runtime/Transports/UTP/UnityTransport.cs | 18 ++++- 4 files changed, 152 insertions(+), 19 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index 96f0223ef3..8d933c5520 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -373,10 +373,14 @@ private ulong GetServerTransportId() { if (NetworkManager != null) { - var transport = NetworkManager.NetworkConfig.NetworkTransport; - if (transport != null) + if (Transport == null && NetworkManager.NetworkConfig.NetworkTransport != null) + { + Transport = NetworkManager.NetworkConfig.NetworkTransport; + } + + if (Transport) { - return transport.ServerClientId; + return Transport.ServerClientId; } throw new NullReferenceException($"The transport in the active {nameof(NetworkConfig)} is null"); @@ -412,7 +416,7 @@ internal void PollAndHandleNetworkEvents() NetworkEvent networkEvent; do { - networkEvent = NetworkManager.NetworkConfig.NetworkTransport.PollEvent(out ulong transportClientId, out ArraySegment payload, out float receiveTime); + networkEvent = Transport.PollEvent(out ulong transportClientId, out ArraySegment payload, out float receiveTime); HandleNetworkEvent(networkEvent, transportClientId, payload, receiveTime); if (networkEvent == NetworkEvent.Disconnect || networkEvent == NetworkEvent.TransportFailure) { @@ -520,6 +524,22 @@ internal void DataEventHandler(ulong transportClientId, ref ArraySegment p #endif } + private void GenerateDisconnectInformation(ulong clientId, ulong transportClientId, string reason = null) + { + var header = $"[Disconnect Event][Client-{clientId}]"; + var existingDisconnectReason = DisconnectReason; + var defaultMessage = reason ?? $"Disconnected."; + // Just go ahead and set this whether client or server so any subscriptions to a disconnect event can check the DisconnectReason + // to determine why the client disconnected + DisconnectReason = Transport.DisconnectEvent == NetworkTransport.DisconnectEvents.Disconnected ? $"{header} {defaultMessage}" : + $"{header}[{Transport.DisconnectEvent}] {defaultMessage}"; + DisconnectReason = $"{DisconnectReason}\n{existingDisconnectReason}"; + if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) + { + NetworkLog.LogInfo($"{DisconnectReason}"); + } + } + /// /// Handles a event. /// @@ -528,11 +548,8 @@ internal void DisconnectEventHandler(ulong transportClientId) #if DEVELOPMENT_BUILD || UNITY_EDITOR s_TransportDisconnect.Begin(); #endif - var clientId = TransportIdCleanUp(transportClientId); - if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) - { - NetworkLog.LogInfo($"Disconnect Event From {clientId}"); - } + var clientId = TransportIdToClientId(transportClientId); + TransportIdCleanUp(transportClientId); // If we are a client and we have gotten the ServerClientId back, then use our assigned local id as the client that was // disconnected (either the user disconnected or the server disconnected, but the client that disconnected is the LocalClientId) @@ -541,6 +558,8 @@ internal void DisconnectEventHandler(ulong transportClientId) clientId = NetworkManager.LocalClientId; } + GenerateDisconnectInformation(clientId, transportClientId); + // Process the incoming message queue so that we get everything from the server disconnecting us or, if we are the server, so we got everything from that client. MessageManager.ProcessIncomingMessageQueue(); @@ -1327,7 +1346,7 @@ internal void OnClientDisconnectFromServer(ulong clientId) if (ClientIdToTransportIdMap.ContainsKey(clientId)) { var transportId = ClientIdToTransportId(clientId); - NetworkManager.NetworkConfig.NetworkTransport.DisconnectRemoteClient(transportId); + Transport.DisconnectRemoteClient(transportId); InvokeOnClientDisconnectCallback(clientId); @@ -1393,10 +1412,15 @@ internal void DisconnectClient(ulong clientId, string reason = null) }; SendMessage(ref disconnectReason, NetworkDelivery.Reliable, clientId); } + Transport.SetDisconnectEvent((byte)Networking.Transport.Error.DisconnectReason.Default); + GenerateDisconnectInformation(clientId, ClientIdToTransportId(clientId), reason); DisconnectRemoteClient(clientId); } + internal NetworkTransport Transport; + internal NetworkTransport.DisconnectEvents DisconnectEvent => Transport ? Transport.DisconnectEvent : NetworkTransport.DisconnectEvents.Disconnected; + /// /// Should be invoked when starting a server-host or client /// @@ -1418,10 +1442,14 @@ internal void Initialize(NetworkManager networkManager) NetworkManager = networkManager; MessageManager = networkManager.MessageManager; - NetworkManager.NetworkConfig.NetworkTransport.NetworkMetrics = NetworkManager.MetricsManager.NetworkMetrics; - - NetworkManager.NetworkConfig.NetworkTransport.OnTransportEvent += HandleNetworkEvent; - NetworkManager.NetworkConfig.NetworkTransport.Initialize(networkManager); + Transport = NetworkManager.NetworkConfig.NetworkTransport; + if (Transport) + { + Transport.NetworkMetrics = NetworkManager.MetricsManager.NetworkMetrics; + Transport.OnTransportEvent += HandleNetworkEvent; + Transport.Initialize(networkManager); + Transport.CreateDisconnectEventMap(); + } } /// @@ -1435,7 +1463,7 @@ internal void Shutdown() var disconnectedIds = new HashSet(); //Don't know if I have to disconnect the clients. I'm assuming the NetworkTransport does all the cleaning on shutdown. But this way the clients get a disconnect message from server (so long it does't get lost) - var serverTransportId = NetworkManager.NetworkConfig.NetworkTransport.ServerClientId; + var serverTransportId = GetServerTransportId(); foreach (KeyValuePair pair in ConnectedClients) { if (!disconnectedIds.Contains(pair.Key)) @@ -1478,7 +1506,7 @@ internal void Shutdown() // Client only, send disconnect and if transport throws and exception, log the exception and continue the shutdown sequence (or forever be shutting down) try { - NetworkManager.NetworkConfig.NetworkTransport.DisconnectLocalClient(); + Transport.DisconnectLocalClient(); } catch (Exception ex) { @@ -1508,6 +1536,11 @@ internal void Shutdown() var transport = NetworkManager.NetworkConfig?.NetworkTransport; if (transport != null) { + if (LocalClient.IsServer) + { + GenerateDisconnectInformation(NetworkManager.ServerClientId, Transport.ServerClientId, "Disconnecting due to shutdown."); + } + transport.CleanDisconnectEventMap(); transport.Shutdown(); if (NetworkManager.LogLevel <= LogLevel.Developer) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index cff2768405..289d28a010 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Unity.Collections; using System.Linq; +using Unity.Netcode.Components; using UnityEngine; #if UNITY_EDITOR using UnityEditor; @@ -9,7 +10,6 @@ #endif using UnityEngine.SceneManagement; using Debug = UnityEngine.Debug; -using Unity.Netcode.Components; namespace Unity.Netcode { @@ -611,6 +611,16 @@ public ulong LocalClientId /// public string DisconnectReason => ConnectionManager.DisconnectReason; + /// + /// If supported by the , this property will be set for each disconnect event. + /// If not supported, then this remain as the default value. + /// + /// + /// A server/host will receive notifications for remote clients disconnecting and will update this property + /// upon each disconnect event.
+ ///
+ public NetworkTransport.DisconnectEvents DisconnectEvent => ConnectionManager.DisconnectEvent; + /// /// Is true when a server or host is listening for connections. /// Is true when a client is connecting or connected to a network session. @@ -1485,7 +1495,7 @@ private void HostServerInitialize() /// Disconnects the remote client. /// /// The ClientId to disconnect - public void DisconnectClient(ulong clientId) => ConnectionManager.DisconnectClient(clientId); + public void DisconnectClient(ulong clientId) => ConnectionManager.DisconnectClient(clientId, $"Client-{clientId} disconnected by server."); /// /// Disconnects the remote client. diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index b8784fcfb3..4673a16958 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using UnityEngine; namespace Unity.Netcode @@ -164,6 +165,79 @@ internal NetworkTopologyTypes CurrentTopology() { return OnCurrentTopology(); } + + + public enum DisconnectEvents : byte + { + Disconnected, + ProtocolTimeout, + MaxConnectionAttempts, + ClosedByRemote, + ClosedRemoteConnection, + AuthenticationFailure, + ProtocolError, + } + + public DisconnectEvents DisconnectEvent { get; private set; } + private Dictionary m_DisconnectEventMap = new Dictionary(); + + /// + /// This should be invoked by the derived class when a transport level disconnect event occurs.
+ /// If there is a map for the specific transport event id, then will be set to the equivalent value. + ///
+ /// The transport's disconnect event identifer. + public void SetDisconnectEvent(byte disconnectEventId) + { + if (m_DisconnectEventMap.ContainsKey(disconnectEventId)) + { + DisconnectEvent = m_DisconnectEventMap[disconnectEventId]; + } + else // If there are no maps, then this will always report just disconnected. + { + DisconnectEvent = DisconnectEvents.Disconnected; + } + } + + internal void SetDisconnectEvent(DisconnectEvents disconnectEvent) + { + DisconnectEvent = disconnectEvent; + } + + /// + /// Adds a map between the value and the transports equivalent event identifier. + /// + /// The value to be mapped. + /// The transport's equivalent event identifier value. + protected void AddDisconnectEventMap(DisconnectEvents disconnectEvents, byte targetEventId) + { + if (!m_DisconnectEventMap.ContainsKey(targetEventId)) + { + m_DisconnectEventMap.Add(targetEventId, disconnectEvents); + } + } + + /// + /// Override this method to create a disconnect event mapping table that will translate the transport's equivalent for each enum in .
+ /// This method is invoked during just after has been invoked. + ///
+ /// + /// You can use to register a map between and the transport's disconnect event equivalent. + /// + protected virtual void OnCreateDisconnectEventMap() + { + + } + + internal void CreateDisconnectEventMap() + { + OnCreateDisconnectEventMap(); + } + + internal void CleanDisconnectEventMap() + { + DisconnectEvent = DisconnectEvents.Disconnected; + m_DisconnectEventMap.Clear(); + } } /// diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 84513fde66..5bb2c7589d 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -15,9 +15,11 @@ using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; using Unity.Networking.Transport; +using Unity.Networking.Transport.Error; using Unity.Networking.Transport.Relay; using Unity.Networking.Transport.TLS; using Unity.Networking.Transport.Utilities; +using UnityEditor.PackageManager; using UnityEngine; using NetcodeEvent = Unity.Netcode.NetworkEvent; @@ -1056,6 +1058,9 @@ private bool ProcessEvent() Debug.LogError("Failed to connect to server."); } + // Set the disconnect event error code + SetDisconnectEvent(reader.ReadByte()); + m_ServerClientId = default; m_ReliableReceiveQueues.Remove(clientId); ClearSendQueuesForClientId(clientId); @@ -1348,7 +1353,7 @@ public override void DisconnectRemoteClient(ulong clientId) } #endif - if (m_Driver.IsCreated) + if (m_NetworkManager.IsServer && m_Driver.IsCreated) { FlushSendQueuesForClientId(clientId); @@ -1363,6 +1368,17 @@ public override void DisconnectRemoteClient(ulong clientId) } } + protected override void OnCreateDisconnectEventMap() + { + AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default); + AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout); + AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts); + AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote); + AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure); + AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError); + base.OnCreateDisconnectEventMap(); + } + /// /// Gets the current RTT for a specific client /// From e28c90433361ad7ec88aaed92228a7174abfb95a Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Wed, 16 Jul 2025 13:21:23 -0500 Subject: [PATCH 02/19] Update Adding some final adjustments and (hopefully) improving the disconnect event messaging upon a local client or server shutting down. --- .../Connection/NetworkConnectionManager.cs | 37 +++++++++++----- .../Runtime/Transports/NetworkTransport.cs | 42 +++++++++++++++++-- .../SinglePlayer/SinglePlayerTransport.cs | 1 - .../Runtime/Transports/UTP/UnityTransport.cs | 23 +++++++--- 4 files changed, 82 insertions(+), 21 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index 8d933c5520..92d71af9f8 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -528,12 +528,17 @@ private void GenerateDisconnectInformation(ulong clientId, ulong transportClient { var header = $"[Disconnect Event][Client-{clientId}]"; var existingDisconnectReason = DisconnectReason; - var defaultMessage = reason ?? $"Disconnected."; + + var defaultMessage = Transport.DisconnectEventMessage; + if (reason != null) + { + defaultMessage = $"{reason} {defaultMessage}"; + } // Just go ahead and set this whether client or server so any subscriptions to a disconnect event can check the DisconnectReason // to determine why the client disconnected - DisconnectReason = Transport.DisconnectEvent == NetworkTransport.DisconnectEvents.Disconnected ? $"{header} {defaultMessage}" : - $"{header}[{Transport.DisconnectEvent}] {defaultMessage}"; + DisconnectReason = $"{header}[{Transport.DisconnectEvent}] {defaultMessage}"; DisconnectReason = $"{DisconnectReason}\n{existingDisconnectReason}"; + if (NetworkLog.CurrentLogLevel <= LogLevel.Developer) { NetworkLog.LogInfo($"{DisconnectReason}"); @@ -558,7 +563,13 @@ internal void DisconnectEventHandler(ulong transportClientId) clientId = NetworkManager.LocalClientId; } - GenerateDisconnectInformation(clientId, transportClientId); + // If the disconnect is due to the transport being shutdown and we have received a notification + // from transport that we have disconnected, then we are a client that has shutdown the NetworkManager + // and there is no need to generate any disconnect information as all of that should already be set at this point. + if (Transport.DisconnectEvent != NetworkTransport.DisconnectEvents.TransportShutdown) + { + GenerateDisconnectInformation(clientId, transportClientId); + } // Process the incoming message queue so that we get everything from the server disconnecting us or, if we are the server, so we got everything from that client. MessageManager.ProcessIncomingMessageQueue(); @@ -1412,8 +1423,8 @@ internal void DisconnectClient(ulong clientId, string reason = null) }; SendMessage(ref disconnectReason, NetworkDelivery.Reliable, clientId); } - Transport.SetDisconnectEvent((byte)Networking.Transport.Error.DisconnectReason.Default); + Transport.ClosingRemoteConnection(); GenerateDisconnectInformation(clientId, ClientIdToTransportId(clientId), reason); DisconnectRemoteClient(clientId); } @@ -1457,6 +1468,14 @@ internal void Initialize(NetworkManager networkManager) /// internal void Shutdown() { + if (Transport && IsListening) + { + var clientId = NetworkManager ? NetworkManager.LocalClientId : NetworkManager.ServerClientId; + var transportId = ClientIdToTransportId(clientId); + Transport.SetDisconnectEvent(NetworkTransport.DisconnectEvents.TransportShutdown); + GenerateDisconnectInformation(clientId, transportId, $"{nameof(NetworkConnectionManager)} was shutdown."); + } + if (LocalClient.IsServer) { // Build a list of all client ids to be disconnected @@ -1506,7 +1525,8 @@ internal void Shutdown() // Client only, send disconnect and if transport throws and exception, log the exception and continue the shutdown sequence (or forever be shutting down) try { - Transport.DisconnectLocalClient(); + Transport?.DisconnectLocalClient(); + Transport?.CleanDisconnectEventMap(); } catch (Exception ex) { @@ -1536,13 +1556,8 @@ internal void Shutdown() var transport = NetworkManager.NetworkConfig?.NetworkTransport; if (transport != null) { - if (LocalClient.IsServer) - { - GenerateDisconnectInformation(NetworkManager.ServerClientId, Transport.ServerClientId, "Disconnecting due to shutdown."); - } transport.CleanDisconnectEventMap(); transport.Shutdown(); - if (NetworkManager.LogLevel <= LogLevel.Developer) { NetworkLog.LogInfo($"{nameof(NetworkConnectionManager)}.{nameof(Shutdown)}() -> {nameof(IsListening)} && {nameof(NetworkManager.NetworkConfig.NetworkTransport)} != null -> {nameof(NetworkTransport)}.{nameof(NetworkTransport.Shutdown)}()"); diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index 4673a16958..3f863e8eb8 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -169,6 +169,7 @@ internal NetworkTopologyTypes CurrentTopology() public enum DisconnectEvents : byte { + TransportShutdown, Disconnected, ProtocolTimeout, MaxConnectionAttempts, @@ -179,14 +180,17 @@ public enum DisconnectEvents : byte } public DisconnectEvents DisconnectEvent { get; private set; } + public string DisconnectEventMessage { get; private set; } + private Dictionary m_DisconnectEventMap = new Dictionary(); + private Dictionary m_DisconnectEventMessageMap = new Dictionary(); /// /// This should be invoked by the derived class when a transport level disconnect event occurs.
/// If there is a map for the specific transport event id, then will be set to the equivalent value. ///
/// The transport's disconnect event identifer. - public void SetDisconnectEvent(byte disconnectEventId) + public void SetDisconnectEvent(byte disconnectEventId, string message = null) { if (m_DisconnectEventMap.ContainsKey(disconnectEventId)) { @@ -196,11 +200,29 @@ public void SetDisconnectEvent(byte disconnectEventId) { DisconnectEvent = DisconnectEvents.Disconnected; } + DisconnectEventMessage = string.Empty; + if (message != null) + { + DisconnectEventMessage = message; + } + else if (m_DisconnectEventMessageMap.ContainsKey(DisconnectEvent)) + { + DisconnectEventMessage = m_DisconnectEventMessageMap[DisconnectEvent]; + } } - internal void SetDisconnectEvent(DisconnectEvents disconnectEvent) + internal void SetDisconnectEvent(DisconnectEvents disconnectEvent, string message = null) { DisconnectEvent = disconnectEvent; + DisconnectEventMessage = string.Empty; + if (message != null) + { + DisconnectEventMessage = message; + } + else if (m_DisconnectEventMessageMap.ContainsKey(disconnectEvent)) + { + DisconnectEventMessage = m_DisconnectEventMessageMap[disconnectEvent]; + } } /// @@ -208,12 +230,18 @@ internal void SetDisconnectEvent(DisconnectEvents disconnectEvent) /// /// The value to be mapped. /// The transport's equivalent event identifier value. - protected void AddDisconnectEventMap(DisconnectEvents disconnectEvents, byte targetEventId) + /// Optional message to use for this disconnect event. + protected void AddDisconnectEventMap(DisconnectEvents disconnectEvents, byte targetEventId, string message = null) { if (!m_DisconnectEventMap.ContainsKey(targetEventId)) { m_DisconnectEventMap.Add(targetEventId, disconnectEvents); } + + if (message != null && !m_DisconnectEventMessageMap.ContainsKey(disconnectEvents)) + { + m_DisconnectEventMessageMap.Add(disconnectEvents, message); + } } /// @@ -230,6 +258,8 @@ protected virtual void OnCreateDisconnectEventMap() internal void CreateDisconnectEventMap() { + DisconnectEvent = DisconnectEvents.Disconnected; + DisconnectEventMessage = string.Empty; OnCreateDisconnectEventMap(); } @@ -237,6 +267,12 @@ internal void CleanDisconnectEventMap() { DisconnectEvent = DisconnectEvents.Disconnected; m_DisconnectEventMap.Clear(); + m_DisconnectEventMessageMap.Clear(); + } + + internal void ClosingRemoteConnection() + { + SetDisconnectEvent(DisconnectEvents.ClosedRemoteConnection); } } diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/SinglePlayer/SinglePlayerTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/SinglePlayer/SinglePlayerTransport.cs index 17a240b676..e113d48c06 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/SinglePlayer/SinglePlayerTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/SinglePlayer/SinglePlayerTransport.cs @@ -28,7 +28,6 @@ private struct MessageData private static Dictionary> s_MessageQueue = new Dictionary>(); - private bool m_Initialized; private ulong m_TransportId = 0; private NetworkManager m_NetworkManager; diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 5bb2c7589d..0be2b007bd 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1368,14 +1368,25 @@ public override void DisconnectRemoteClient(ulong clientId) } } + private const byte k_ClosedRemoteConnection = 128; + private const byte k_TransportShutdown = 129; + + /// protected override void OnCreateDisconnectEventMap() { - AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default); - AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout); - AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts); - AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote); - AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure); - AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError); + // Implemented in UTP + + AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default, "Gracefully disconnected."); + AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout, "Connection timed out."); + AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts, "Maximum connection attempts reached."); + AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote, "Remote connection was closed."); + AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure, "Authentication failed."); + AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError, "Transport protocol error encountered."); + + // Not implemented in UTP + AddDisconnectEventMap(DisconnectEvents.ClosedRemoteConnection, k_ClosedRemoteConnection, "Local transport closed the remote connection."); + AddDisconnectEventMap(DisconnectEvents.TransportShutdown, k_TransportShutdown, "The transport was shutdown."); + base.OnCreateDisconnectEventMap(); } From 486ab1c52e00a417ec019196246f07ae275e385f Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Wed, 16 Jul 2025 21:21:45 -0500 Subject: [PATCH 03/19] fix When using NotMeRpc, make sure we only send to connected clients and not the service to avoid infinite spamming of the RPC. --- .../Runtime/Messaging/RpcTargets/NotMeRpcTarget.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/NotMeRpcTarget.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/NotMeRpcTarget.cs index 5ea687101c..681c8909a4 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/NotMeRpcTarget.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/RpcTargets/NotMeRpcTarget.cs @@ -49,8 +49,11 @@ internal override void Send(NetworkBehaviour behaviour, ref RpcMessage message, { continue; } - // In distributed authority mode, we send to target id 0 (which would be a DAHost) via the group - if (clientId == NetworkManager.ServerClientId && !m_NetworkManager.DistributedAuthorityMode) + // In distributed authority mode, we send to target id 0 (which would be a DAHost). + // We only add when there is a "DAHost" by + // - excluding the server id when using client-server (i.e. !m_NetworkManager.DistributedAuthorityMode ) + // - excluding if connected to the CMB backend service (i.e. we don't want to send to service as it will broadcast it back) + if (clientId == NetworkManager.ServerClientId && (!m_NetworkManager.DistributedAuthorityMode || m_NetworkManager.CMBServiceConnection)) { continue; } From a7745cb7e2237911f75b2e04f0b88c89ec81d424 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Wed, 16 Jul 2025 21:31:17 -0500 Subject: [PATCH 04/19] update Adding additional comments and disconnect event specific messages for UnityTransport. --- .../Runtime/Transports/NetworkTransport.cs | 39 ++++++++++++++++++- .../Runtime/Transports/UTP/UnityTransport.cs | 26 ++++++++----- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index 3f863e8eb8..8277257413 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -166,20 +166,57 @@ internal NetworkTopologyTypes CurrentTopology() return OnCurrentTopology(); } - + /// + /// The Netcode for GameObjects standardized disconnection event types. + /// + /// + /// provides you with the ability to register the transport's disconnect event types with the local equivalent. + /// public enum DisconnectEvents : byte { + /// + /// If transport has mapped its disconnect events, this event signifies that the transport closed the connection due to a locally invoked shutdown. + /// TransportShutdown, + /// + /// If transport has mapped its disconnect events, this event signifies a graceful disconnect. + /// Disconnected, + /// + /// If transport has mapped its disconnect events, this event signifies that the transport's connection to the endpoint has timed out and the connection was closed. + /// ProtocolTimeout, + /// + /// If transport has mapped its disconnect events, this event signifies that the disconnect is due to the maximum number of failed connection attempts has been reached. + /// MaxConnectionAttempts, + /// + /// If transport has mapped its disconnect events, this event signifies that the remote endpoint closed the connection. + /// ClosedByRemote, + /// + /// If transport has mapped its disconnect events, this event signifies the local transport closed the incoming remote endpoint connection. + /// ClosedRemoteConnection, + /// + /// If transport has mapped its disconnect events, this event signifies that the connection was closed due to an authentication failure. + /// AuthenticationFailure, + /// + /// If transport has mapped its disconnect events, this event signifies that a lower-level (unkown) transport error occurred. + /// ProtocolError, } + /// + /// If the transport has implemented disconnection event mapping, then this will be set to the most recent disconnection event. + /// public DisconnectEvents DisconnectEvent { get; private set; } + + /// + /// If the transport has implemented disconnection event mapping and disconnection event message mapping, then this will contain + /// the transport specific message associated with the disconnect event type. + /// public string DisconnectEventMessage { get; private set; } private Dictionary m_DisconnectEventMap = new Dictionary(); diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 0be2b007bd..a9b047c78b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -19,7 +19,6 @@ using Unity.Networking.Transport.Relay; using Unity.Networking.Transport.TLS; using Unity.Networking.Transport.Utilities; -using UnityEditor.PackageManager; using UnityEngine; using NetcodeEvent = Unity.Netcode.NetworkEvent; @@ -1371,21 +1370,30 @@ public override void DisconnectRemoteClient(ulong clientId) private const byte k_ClosedRemoteConnection = 128; private const byte k_TransportShutdown = 129; + internal const string DisconnectedMessage = "Gracefully disconnected."; + internal const string TimeoutMessage = "Connection closed due to timed out."; + internal const string MaxConnectionAttemptsMessage = "Connection closed due to maximum connection attempts reached."; + internal const string ClosedByRemoteMessage = "Connection was closed by remote endpoint."; + internal const string AuthenticationFailureMessage = "Connection closed due to authentication failure."; + internal const string ProtocolErrorMessage = "Gracefully disconnected."; + internal const string ClosedRemoteConnectionMessage = "Local transport closed the remote endpoint connection."; + internal const string TransportShutdownMessage = "The transport was shutdown."; + /// protected override void OnCreateDisconnectEventMap() { // Implemented in UTP - AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default, "Gracefully disconnected."); - AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout, "Connection timed out."); - AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts, "Maximum connection attempts reached."); - AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote, "Remote connection was closed."); - AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure, "Authentication failed."); - AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError, "Transport protocol error encountered."); + AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default, DisconnectedMessage); + AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout, TimeoutMessage); + AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts, MaxConnectionAttemptsMessage); + AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote, ClosedByRemoteMessage); + AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure, AuthenticationFailureMessage); + AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError, ProtocolErrorMessage); // Not implemented in UTP - AddDisconnectEventMap(DisconnectEvents.ClosedRemoteConnection, k_ClosedRemoteConnection, "Local transport closed the remote connection."); - AddDisconnectEventMap(DisconnectEvents.TransportShutdown, k_TransportShutdown, "The transport was shutdown."); + AddDisconnectEventMap(DisconnectEvents.ClosedRemoteConnection, k_ClosedRemoteConnection, ClosedRemoteConnectionMessage); + AddDisconnectEventMap(DisconnectEvents.TransportShutdown, k_TransportShutdown, TransportShutdownMessage); base.OnCreateDisconnectEventMap(); } From 1931fbb5e7ec2da39ec7f32faa01a08e8d005e46 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Wed, 16 Jul 2025 21:44:50 -0500 Subject: [PATCH 05/19] style - PVP Missed a parameter in the XML-API --- .../Runtime/Transports/NetworkTransport.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index 8277257413..723db34b5c 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -227,7 +227,8 @@ public enum DisconnectEvents : byte /// If there is a map for the specific transport event id, then will be set to the equivalent value. /// /// The transport's disconnect event identifer. - public void SetDisconnectEvent(byte disconnectEventId, string message = null) + /// Optional message to override any existing registered one for the transport specific disconnection event identifier. + public void SetDisconnectEvent(byte disconnectEventId, string messageOverride = null) { if (m_DisconnectEventMap.ContainsKey(disconnectEventId)) { @@ -238,9 +239,9 @@ public void SetDisconnectEvent(byte disconnectEventId, string message = null) DisconnectEvent = DisconnectEvents.Disconnected; } DisconnectEventMessage = string.Empty; - if (message != null) + if (messageOverride != null) { - DisconnectEventMessage = message; + DisconnectEventMessage = messageOverride; } else if (m_DisconnectEventMessageMap.ContainsKey(DisconnectEvent)) { From 3a065119869d9d8600d5595d0e9eeecd8e6d0e5b Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Thu, 17 Jul 2025 12:24:22 -0500 Subject: [PATCH 06/19] test - fix Fixing some minor test issues after the disconnect notification updates. --- .../Runtime/Transports/UTP/UnityTransport.cs | 4 +++- .../DistributedAuthority/SessionVersionConnectionRequest.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index a9b047c78b..37e3f5615d 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1352,7 +1352,9 @@ public override void DisconnectRemoteClient(ulong clientId) } #endif - if (m_NetworkManager.IsServer && m_Driver.IsCreated) + var hasAuthority = m_NetworkManager ? m_NetworkManager.IsServer : true; + + if (hasAuthority && m_Driver.IsCreated) { FlushSendQueuesForClientId(clientId); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/SessionVersionConnectionRequest.cs b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/SessionVersionConnectionRequest.cs index d537903d8e..4a436457c0 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/SessionVersionConnectionRequest.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/DistributedAuthority/SessionVersionConnectionRequest.cs @@ -96,7 +96,7 @@ public IEnumerator ValidateSessionVersion([Values] SessionVersionType type) { yield return WaitForConditionOrTimeOut(() => m_ClientWasDisconnected); AssertOnTimeout("Client was not disconnected when it should have been!"); - Assert.True(m_ClientNetworkManager.DisconnectReason == ConnectionRequestMessage.InvalidSessionVersionMessage, "Client did not receive the correct invalid session version message!"); + Assert.True(m_ClientNetworkManager.DisconnectReason.Contains(ConnectionRequestMessage.InvalidSessionVersionMessage), "Client did not receive the correct invalid session version message!"); } else { From cff9df659da8ec7e9373901b9cecde4ccd2cae53 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Thu, 17 Jul 2025 13:26:11 -0500 Subject: [PATCH 07/19] test Updating the multi-client test. --- .../Assets/Tests/Runtime/MultiClientConnectionApproval.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs b/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs index cb85f0baa9..61a8a8d112 100644 --- a/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs +++ b/testproject/Assets/Tests/Runtime/MultiClientConnectionApproval.cs @@ -22,6 +22,8 @@ public class MultiClientConnectionApproval private bool m_DelayedApproval; private List m_ResponseToSet = new List(); + private const string k_DisconnectMessage = "Some valid reason"; + [OneTimeSetUp] public void OneTimeSetup() { @@ -180,7 +182,7 @@ private IEnumerator ConnectionApprovalHandler(int numClients, int failureTestCou foreach (var c in clientsToClean) { - Assert.AreEqual(c.DisconnectReason, "Some valid reason"); + Assert.IsTrue(c.DisconnectReason.Contains(k_DisconnectMessage), $"The disconnect message ({c.DisconnectReason}) does not contain the disconnect information ({k_DisconnectMessage})!"); } foreach (var client in clients) @@ -242,7 +244,7 @@ private void ConnectionApprovalCallback(NetworkManager.ConnectionApprovalRequest } if (!response.Approved) { - response.Reason = "Some valid reason"; + response.Reason = k_DisconnectMessage; } else { From acdfdcf265cbd40cec1d9cd2342d0e108bba738d Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 1 Aug 2025 14:59:04 -0500 Subject: [PATCH 08/19] update Making adjustments based on peer review of this branch's PR. --- .../Connection/NetworkConnectionManager.cs | 5 +- .../Runtime/Transports/NetworkTransport.cs | 91 +++------- .../Runtime/Transports/UTP/UnityTransport.cs | 156 +++++++++++------- 3 files changed, 123 insertions(+), 129 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index e2eb27a3b5..d3b899cb3c 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -1459,7 +1459,6 @@ internal void Initialize(NetworkManager networkManager) Transport.NetworkMetrics = NetworkManager.MetricsManager.NetworkMetrics; Transport.OnTransportEvent += HandleNetworkEvent; Transport.Initialize(networkManager); - Transport.CreateDisconnectEventMap(); } } @@ -1470,9 +1469,9 @@ internal void Shutdown() { if (Transport && IsListening) { + Transport.ShuttingDown(); var clientId = NetworkManager ? NetworkManager.LocalClientId : NetworkManager.ServerClientId; var transportId = ClientIdToTransportId(clientId); - Transport.SetDisconnectEvent(NetworkTransport.DisconnectEvents.TransportShutdown); GenerateDisconnectInformation(clientId, transportId, $"{nameof(NetworkConnectionManager)} was shutdown."); } @@ -1526,7 +1525,6 @@ internal void Shutdown() try { Transport?.DisconnectLocalClient(); - Transport?.CleanDisconnectEventMap(); } catch (Exception ex) { @@ -1556,7 +1554,6 @@ internal void Shutdown() var transport = NetworkManager.NetworkConfig?.NetworkTransport; if (transport != null) { - transport.CleanDisconnectEventMap(); transport.Shutdown(); if (NetworkManager.LogLevel <= LogLevel.Developer) { diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index 723db34b5c..bec51c0e76 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using UnityEngine; namespace Unity.Netcode @@ -172,7 +171,7 @@ internal NetworkTopologyTypes CurrentTopology() /// /// provides you with the ability to register the transport's disconnect event types with the local equivalent. /// - public enum DisconnectEvents : byte + public enum DisconnectEvents { /// /// If transport has mapped its disconnect events, this event signifies that the transport closed the connection due to a locally invoked shutdown. @@ -219,98 +218,52 @@ public enum DisconnectEvents : byte /// public string DisconnectEventMessage { get; private set; } - private Dictionary m_DisconnectEventMap = new Dictionary(); - private Dictionary m_DisconnectEventMessageMap = new Dictionary(); - /// /// This should be invoked by the derived class when a transport level disconnect event occurs.
- /// If there is a map for the specific transport event id, then will be set to the equivalent value. + /// It is up to the derived class to create a map between the transport's disconnect events and the + /// pre-defined enum values. ///
- /// The transport's disconnect event identifer. - /// Optional message to override any existing registered one for the transport specific disconnection event identifier. - public void SetDisconnectEvent(byte disconnectEventId, string messageOverride = null) - { - if (m_DisconnectEventMap.ContainsKey(disconnectEventId)) - { - DisconnectEvent = m_DisconnectEventMap[disconnectEventId]; - } - else // If there are no maps, then this will always report just disconnected. - { - DisconnectEvent = DisconnectEvents.Disconnected; - } - DisconnectEventMessage = string.Empty; - if (messageOverride != null) - { - DisconnectEventMessage = messageOverride; - } - else if (m_DisconnectEventMessageMap.ContainsKey(DisconnectEvent)) - { - DisconnectEventMessage = m_DisconnectEventMessageMap[DisconnectEvent]; - } - } - - internal void SetDisconnectEvent(DisconnectEvents disconnectEvent, string message = null) + /// The type to set. + /// An optional message override. + protected void SetDisconnectEvent(DisconnectEvents disconnectEvent, string message = null) { DisconnectEvent = disconnectEvent; DisconnectEventMessage = string.Empty; + if (message != null) { DisconnectEventMessage = message; } - else if (m_DisconnectEventMessageMap.ContainsKey(disconnectEvent)) + else { - DisconnectEventMessage = m_DisconnectEventMessageMap[disconnectEvent]; + DisconnectEventMessage = OnGetDisconnectEventMessage(disconnectEvent); } } /// - /// Adds a map between the value and the transports equivalent event identifier. + /// Override this method to provide additional information about the disconnection event. /// - /// The value to be mapped. - /// The transport's equivalent event identifier value. - /// Optional message to use for this disconnect event. - protected void AddDisconnectEventMap(DisconnectEvents disconnectEvents, byte targetEventId, string message = null) + /// The disconnect event to get from the derived class. + /// as a default or if overridden the returned. + protected virtual string OnGetDisconnectEventMessage(DisconnectEvents disconnectEvent) { - if (!m_DisconnectEventMap.ContainsKey(targetEventId)) - { - m_DisconnectEventMap.Add(targetEventId, disconnectEvents); - } - - if (message != null && !m_DisconnectEventMessageMap.ContainsKey(disconnectEvents)) - { - m_DisconnectEventMessageMap.Add(disconnectEvents, message); - } + return string.Empty; } /// - /// Override this method to create a disconnect event mapping table that will translate the transport's equivalent for each enum in .
- /// This method is invoked during just after has been invoked. + /// Invoked when the local forces the transport to close a remote connection. ///
- /// - /// You can use to register a map between and the transport's disconnect event equivalent. - /// - protected virtual void OnCreateDisconnectEventMap() - { - - } - - internal void CreateDisconnectEventMap() - { - DisconnectEvent = DisconnectEvents.Disconnected; - DisconnectEventMessage = string.Empty; - OnCreateDisconnectEventMap(); - } - - internal void CleanDisconnectEventMap() + internal void ClosingRemoteConnection() { - DisconnectEvent = DisconnectEvents.Disconnected; - m_DisconnectEventMap.Clear(); - m_DisconnectEventMessageMap.Clear(); + SetDisconnectEvent(DisconnectEvents.ClosedRemoteConnection); } - internal void ClosingRemoteConnection() + /// + /// Invoked just before the transport is shutdown. + /// + internal void ShuttingDown() { - SetDisconnectEvent(DisconnectEvents.ClosedRemoteConnection); + SetDisconnectEvent(DisconnectEvents.TransportShutdown); } } diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 37e3f5615d..4100c0e4b4 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1058,7 +1058,8 @@ private bool ProcessEvent() } // Set the disconnect event error code - SetDisconnectEvent(reader.ReadByte()); + var errorCode = m_UnityTransportNotificationHandler.GetDisconnectEvent(reader.ReadByte()); + SetDisconnectEvent(errorCode); m_ServerClientId = default; m_ReliableReceiveQueues.Remove(clientId); @@ -1369,37 +1370,6 @@ public override void DisconnectRemoteClient(ulong clientId) } } - private const byte k_ClosedRemoteConnection = 128; - private const byte k_TransportShutdown = 129; - - internal const string DisconnectedMessage = "Gracefully disconnected."; - internal const string TimeoutMessage = "Connection closed due to timed out."; - internal const string MaxConnectionAttemptsMessage = "Connection closed due to maximum connection attempts reached."; - internal const string ClosedByRemoteMessage = "Connection was closed by remote endpoint."; - internal const string AuthenticationFailureMessage = "Connection closed due to authentication failure."; - internal const string ProtocolErrorMessage = "Gracefully disconnected."; - internal const string ClosedRemoteConnectionMessage = "Local transport closed the remote endpoint connection."; - internal const string TransportShutdownMessage = "The transport was shutdown."; - - /// - protected override void OnCreateDisconnectEventMap() - { - // Implemented in UTP - - AddDisconnectEventMap(DisconnectEvents.Disconnected, (byte)DisconnectReason.Default, DisconnectedMessage); - AddDisconnectEventMap(DisconnectEvents.ProtocolTimeout, (byte)DisconnectReason.Timeout, TimeoutMessage); - AddDisconnectEventMap(DisconnectEvents.MaxConnectionAttempts, (byte)DisconnectReason.MaxConnectionAttempts, MaxConnectionAttemptsMessage); - AddDisconnectEventMap(DisconnectEvents.ClosedByRemote, (byte)DisconnectReason.ClosedByRemote, ClosedByRemoteMessage); - AddDisconnectEventMap(DisconnectEvents.AuthenticationFailure, (byte)DisconnectReason.AuthenticationFailure, AuthenticationFailureMessage); - AddDisconnectEventMap(DisconnectEvents.ProtocolError, (byte)DisconnectReason.ProtocolError, ProtocolErrorMessage); - - // Not implemented in UTP - AddDisconnectEventMap(DisconnectEvents.ClosedRemoteConnection, k_ClosedRemoteConnection, ClosedRemoteConnectionMessage); - AddDisconnectEventMap(DisconnectEvents.TransportShutdown, k_TransportShutdown, TransportShutdownMessage); - - base.OnCreateDisconnectEventMap(); - } - /// /// Gets the current RTT for a specific client /// @@ -1449,30 +1419,6 @@ public NetworkEndpoint GetEndpoint(ulong clientId) return new NetworkEndpoint(); } - /// - /// Initializes the transport - /// - /// The NetworkManager that initialized and owns the transport - public override void Initialize(NetworkManager networkManager = null) - { -#if DEBUG - if (sizeof(ulong) != UnsafeUtility.SizeOf()) - { - Debug.LogWarning($"Netcode connection id size {sizeof(ulong)} does not match UTP connection id size {UnsafeUtility.SizeOf()}!"); - return; - } -#endif - - m_NetworkManager = networkManager; - - if (m_NetworkManager && m_NetworkManager.PortOverride.Overidden) - { - ConnectionData.Port = m_NetworkManager.PortOverride.Value; - } - - m_RealTimeProvider = m_NetworkManager ? m_NetworkManager.RealTimeProvider : new RealTimeProvider(); - } - /// /// Polls for incoming events, with an extra output parameter to report the precise time the event was received. /// @@ -1626,6 +1572,39 @@ public override bool StartServer() return succeeded; } + private UnityTransportNotificationHandler m_UnityTransportNotificationHandler; + + /// + protected override string OnGetDisconnectEventMessage(DisconnectEvents disconnectEvent) + { + return m_UnityTransportNotificationHandler.GetDisconnectEventMessage(disconnectEvent); + } + + /// + /// Initializes the transport + /// + /// The NetworkManager that initialized and owns the transport + public override void Initialize(NetworkManager networkManager = null) + { +#if DEBUG + if (sizeof(ulong) != UnsafeUtility.SizeOf()) + { + Debug.LogWarning($"Netcode connection id size {sizeof(ulong)} does not match UTP connection id size {UnsafeUtility.SizeOf()}!"); + return; + } +#endif + + m_NetworkManager = networkManager; + + if (m_NetworkManager && m_NetworkManager.PortOverride.Overidden) + { + ConnectionData.Port = m_NetworkManager.PortOverride.Value; + } + + m_RealTimeProvider = m_NetworkManager ? m_NetworkManager.RealTimeProvider : new RealTimeProvider(); + m_UnityTransportNotificationHandler = new UnityTransportNotificationHandler(); + } + /// /// Shuts down the transport /// @@ -1663,6 +1642,8 @@ public override void Shutdown() // We must reset this to zero because UTP actually re-uses clientIds if there is a clean disconnect m_ServerClientId = default; + + m_UnityTransportNotificationHandler = null; } /// @@ -1849,4 +1830,67 @@ internal static FixedString128Bytes ErrorToFixedString(int error) } } } + + /// + /// Handles mapping to as well + /// as mapping additional disconnect event message information to each . + /// + internal class UnityTransportNotificationHandler + { + private const int k_ClosedRemoteConnection = 128; + private const int k_TransportShutdown = 129; + + internal const string DisconnectedMessage = "Gracefully disconnected."; + internal const string TimeoutMessage = "Connection closed due to timed out."; + internal const string MaxConnectionAttemptsMessage = "Connection closed due to maximum connection attempts reached."; + internal const string ClosedByRemoteMessage = "Connection was closed by remote endpoint."; + internal const string AuthenticationFailureMessage = "Connection closed due to authentication failure."; + internal const string ProtocolErrorMessage = "Gracefully disconnected."; + internal const string ClosedRemoteConnectionMessage = "Local transport closed the remote endpoint connection."; + internal const string TransportShutdownMessage = "The transport was shutdown."; + + private Dictionary m_DisconnectEventMap = new Dictionary(); + private Dictionary m_DisconnectEventMessageMap = new Dictionary(); + + internal NetworkTransport.DisconnectEvents GetDisconnectEvent(int disconnectEventId) + { + return m_DisconnectEventMap.ContainsKey(disconnectEventId) ? m_DisconnectEventMap[disconnectEventId] : NetworkTransport.DisconnectEvents.Disconnected; + } + + public string GetDisconnectEventMessage(NetworkTransport.DisconnectEvents disconnectEvent) + { + return string.Empty; + } + + public void ClosingRemoteConnection() + { + + } + + private void AddDisconnectEventMap(NetworkTransport.DisconnectEvents disconnectEvent, int disconnectReason, string message) + { + m_DisconnectEventMap.Add(disconnectReason, disconnectEvent); + m_DisconnectEventMessageMap.Add(disconnectEvent, message); + } + + private void AddDisconnectEventMap(NetworkTransport.DisconnectEvents disconnectEvent, DisconnectReason disconnectReason, string message) + { + AddDisconnectEventMap(disconnectEvent, (int)disconnectReason, message); + } + + public UnityTransportNotificationHandler() + { + // Implemented in UTP + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.Disconnected, DisconnectReason.Default, DisconnectedMessage); + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.ProtocolTimeout, DisconnectReason.Timeout, TimeoutMessage); + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.MaxConnectionAttempts, DisconnectReason.MaxConnectionAttempts, MaxConnectionAttemptsMessage); + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.ClosedByRemote, DisconnectReason.ClosedByRemote, ClosedByRemoteMessage); + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.AuthenticationFailure, DisconnectReason.AuthenticationFailure, AuthenticationFailureMessage); + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.ProtocolError, DisconnectReason.ProtocolError, ProtocolErrorMessage); + + // Not implemented in UTP + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.ClosedRemoteConnection, k_ClosedRemoteConnection, ClosedRemoteConnectionMessage); + AddDisconnectEventMap(NetworkTransport.DisconnectEvents.TransportShutdown, k_TransportShutdown, TransportShutdownMessage); + } + } } From 20abe4b4e026f15648efeb53c8b47b611320ed36 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 1 Aug 2025 19:44:03 -0500 Subject: [PATCH 09/19] update Adding changelog entries. Trying a possible new "tag" unreleased format. --- com.unity.netcode.gameobjects/CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 489af4f446..67cce02bda 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -10,6 +10,23 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added +- Added disconnection event notification handling capabilities where `NetworkTransport` derived custom transports can set the current disconnect event type (`NetworkTransport.DisconnectEvents`) that, if implemented, will provide more details on why the transport disconnected. (#3551) +- Added protected method `NetworkTransport.SetDisconnectEvent` that a `NetworkTransport` derived custom transport can use to provide the disconnect event type that occurred. (#3551) +- Added protected virtual method `NetworkTransport.OnGetDisconnectEventMessage` that, when overridden, a `NetworkTransport` derived custom transport can use to provide a customized extended message for each `NetworkTransport.DisconnectEvents` value. (#3551) + +### Fixed + +- Fixed issue where the disconnect event and provided message was too generic to know why the disconnect occurred. (#3551) +- Fixed issue where `SendTo.NotMe` could cause an RPC to be delivered to the sender when connected to a live distributed authority session. (#3551) + +### Changed + +- Changed `UnityTransport` now handles setting the current disconnect notification type, via internal `UnityTransportNotificationHandler` class, while also providing extended informational messages for each disconnect event type. (#3551) + +## [Unreleased] (2.5.0) + +### Added + - Added serializer for `Pose` (#3546) - Added methods `GetDefaultNetworkSettings` and `GetDefaultPipelineConfigurations` to `UnityTransport`. These can be used to retrieve the default settings and pipeline stages that are used by `UnityTransport`. This is useful when providing a custom driver constructor through `UnityTransport.s_DriverConstructor`, since it allows reusing or tuning the existing configuration instead of trying to recreate it. This means a transport with a custom driver can now easily benefit from most of the features of `UnityTransport`, like integration with the Network Simulator and Network Profiler from the multiplayer tools package. (#3501) - Added mappings between `ClientId` and `TransportId`. (#3516) From 1f2a52178f870b2f76ffbc50fb38758c073f8f32 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 1 Aug 2025 19:55:52 -0500 Subject: [PATCH 10/19] update Trying out just marking it with a temporary release date. --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 67cce02bda..0a1d33a57c 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -23,7 +23,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Changed `UnityTransport` now handles setting the current disconnect notification type, via internal `UnityTransportNotificationHandler` class, while also providing extended informational messages for each disconnect event type. (#3551) -## [Unreleased] (2.5.0) +## [2.5.0] - 2025-08-01 ### Added From 1468e17dbd4bba0eafe6e3461978047061529cfb Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 15 Aug 2025 11:04:52 -0500 Subject: [PATCH 11/19] update Continuing work on suggested updates to disconnect event notifications. --- .../Runtime/Transports/UTP/UnityTransport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 4100c0e4b4..9873307293 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1859,7 +1859,7 @@ internal NetworkTransport.DisconnectEvents GetDisconnectEvent(int disconnectEven public string GetDisconnectEventMessage(NetworkTransport.DisconnectEvents disconnectEvent) { - return string.Empty; + return m_DisconnectEventMessageMap.ContainsKey(disconnectEvent) ? m_DisconnectEventMessageMap[disconnectEvent] : string.Empty; } public void ClosingRemoteConnection() From 115fbc165ba27306f7529de3c5e9af0bccac2d61 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 15 Aug 2025 13:36:38 -0500 Subject: [PATCH 12/19] update Adjustments for Emma's suggestions/findings. --- .../Runtime/Connection/NetworkConnectionManager.cs | 2 +- .../Runtime/Transports/NetworkTransport.cs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index ecc233c492..82f398a1e6 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -526,7 +526,7 @@ internal void DataEventHandler(ulong transportClientId, ref ArraySegment p private void GenerateDisconnectInformation(ulong clientId, ulong transportClientId, string reason = null) { - var header = $"[Disconnect Event][Client-{clientId}]"; + var header = $"[Disconnect Event][Client-{clientId}][TransportClientId-{transportClientId}]"; var existingDisconnectReason = DisconnectReason; var defaultMessage = Transport.DisconnectEventMessage; diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index bec51c0e76..fee3bfd94f 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -168,9 +168,6 @@ internal NetworkTopologyTypes CurrentTopology() /// /// The Netcode for GameObjects standardized disconnection event types. /// - /// - /// provides you with the ability to register the transport's disconnect event types with the local equivalent. - /// public enum DisconnectEvents { /// From d25ccb4afd0bfbde713f5d1142869306e224bf5c Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 15 Aug 2025 13:42:32 -0500 Subject: [PATCH 13/19] update Some more minor adjustments based on PR feedback. --- .../Runtime/Transports/NetworkTransport.cs | 4 ++-- .../Runtime/Transports/UTP/UnityTransport.cs | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs index fee3bfd94f..122f189127 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/NetworkTransport.cs @@ -233,7 +233,7 @@ protected void SetDisconnectEvent(DisconnectEvents disconnectEvent, string messa } else { - DisconnectEventMessage = OnGetDisconnectEventMessage(disconnectEvent); + DisconnectEventMessage = GetDisconnectEventMessage(disconnectEvent); } } @@ -242,7 +242,7 @@ protected void SetDisconnectEvent(DisconnectEvents disconnectEvent, string messa /// /// The disconnect event to get from the derived class. /// as a default or if overridden the returned. - protected virtual string OnGetDisconnectEventMessage(DisconnectEvents disconnectEvent) + protected virtual string GetDisconnectEventMessage(DisconnectEvents disconnectEvent) { return string.Empty; } diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 4c3122f4b9..b541f3de42 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1518,7 +1518,7 @@ public override bool StartServer() private UnityTransportNotificationHandler m_UnityTransportNotificationHandler; /// - protected override string OnGetDisconnectEventMessage(DisconnectEvents disconnectEvent) + protected override string GetDisconnectEventMessage(DisconnectEvents disconnectEvent) { return m_UnityTransportNotificationHandler.GetDisconnectEventMessage(disconnectEvent); } @@ -1795,21 +1795,22 @@ internal class UnityTransportNotificationHandler private Dictionary m_DisconnectEventMap = new Dictionary(); private Dictionary m_DisconnectEventMessageMap = new Dictionary(); + /// + /// Returns the mapped transport disconnect event id to a value. + /// internal NetworkTransport.DisconnectEvents GetDisconnectEvent(int disconnectEventId) { return m_DisconnectEventMap.ContainsKey(disconnectEventId) ? m_DisconnectEventMap[disconnectEventId] : NetworkTransport.DisconnectEvents.Disconnected; } + /// + /// Returns the disconnect event message for the the disconnect event. + /// public string GetDisconnectEventMessage(NetworkTransport.DisconnectEvents disconnectEvent) { return m_DisconnectEventMessageMap.ContainsKey(disconnectEvent) ? m_DisconnectEventMessageMap[disconnectEvent] : string.Empty; } - public void ClosingRemoteConnection() - { - - } - private void AddDisconnectEventMap(NetworkTransport.DisconnectEvents disconnectEvent, int disconnectReason, string message) { m_DisconnectEventMap.Add(disconnectReason, disconnectEvent); From fea84729e2da8d2127b1ebb458907f839ee89dc6 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 15 Aug 2025 15:27:22 -0500 Subject: [PATCH 14/19] update Making some minor changelog entry modifications based on recent updates. --- com.unity.netcode.gameobjects/CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index b780de0bf6..454c7d62ca 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -13,7 +13,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Added `AsNativeArray()` read‑only accessor to `NetworkList` (#3567) - Added disconnection event notification handling capabilities where `NetworkTransport` derived custom transports can set the current disconnect event type (`NetworkTransport.DisconnectEvents`) that, if implemented, will provide more details on why the transport disconnected. (#3551) - Added protected method `NetworkTransport.SetDisconnectEvent` that a `NetworkTransport` derived custom transport can use to provide the disconnect event type that occurred. (#3551) -- Added protected virtual method `NetworkTransport.OnGetDisconnectEventMessage` that, when overridden, a `NetworkTransport` derived custom transport can use to provide a customized extended message for each `NetworkTransport.DisconnectEvents` value. (#3551) +- Added protected virtual method `NetworkTransport.GetDisconnectEventMessage` that, when overridden, a `NetworkTransport` derived custom transport can use to provide a customized extended message for each `NetworkTransport.DisconnectEvents` value. (#3551) ### Fixed @@ -21,14 +21,15 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed issue where viewing a `NetworkBehaviour` with one or more `NetworkVariable` fields could throw an exception if running a distributed authority network topology with a local (DAHost) host and viewed on the host when the host is not the authority of the associated `NetworkObject`. (#3578) - Fixed issue when using a distributed authority network topology and viewing a `NetworkBehaviour` with one or more `NetworkVariable` fields in the inspector view would not show editable fields. (#3578) - Fixed issue where the disconnect event and provided message was too generic to know why the disconnect occurred. (#3551) -- Fixed issue where `SendTo.NotMe` could cause an RPC to be delivered to the sender when connected to a live distributed authority session. (#3551) - Fixed issue with unnecessary internal GC Allocations when using the `IReadOnlyList` `NetworkManager.ConnectedClientsIds` within a `foreach` statement by either replacing with a `for` loop or directly referencing the `NetworkConnectionManager.ConnectedClientIds`. (#3527) ### Changed - Marked `UnityTransport.ConnectionAddressData.ServerEndPoint` as obsolete. It can't work when using hostnames as the server address, and its functionality can easily be replicated using `NetworkEndpoint.Parse`. (#3591) - Optimized `NetworkList` indexer setter to skip operations when the new value equals the existing value, improving performance by avoiding unnecessary list events and network synchronization. (#3587) -- Changed `UnityTransport` now handles setting the current disconnect notification type, via internal `UnityTransportNotificationHandler` class, while also providing extended informational messages for each disconnect event type. (#3551) +- Changed `UnityTransport` so that it now handles setting the current disconnect notification type, via internal `UnityTransportNotificationHandler` class, while also providing extended informational messages for each disconnect event type. (#3551) +- Changed `SendTo.NotMe` so that it doesn't include the server identifier in the target group when connected to a live distributed authority session. (#3551) + ## [2.5.0] - 2025-08-01 From c07254648e61173be088e91d63d632c34659aeb2 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 15 Aug 2025 15:37:19 -0500 Subject: [PATCH 15/19] update Some additional adjustments for readability and clarity. --- com.unity.netcode.gameobjects/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 454c7d62ca..86e9da12f1 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -13,7 +13,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Added `AsNativeArray()` read‑only accessor to `NetworkList` (#3567) - Added disconnection event notification handling capabilities where `NetworkTransport` derived custom transports can set the current disconnect event type (`NetworkTransport.DisconnectEvents`) that, if implemented, will provide more details on why the transport disconnected. (#3551) - Added protected method `NetworkTransport.SetDisconnectEvent` that a `NetworkTransport` derived custom transport can use to provide the disconnect event type that occurred. (#3551) -- Added protected virtual method `NetworkTransport.GetDisconnectEventMessage` that, when overridden, a `NetworkTransport` derived custom transport can use to provide a customized extended message for each `NetworkTransport.DisconnectEvents` value. (#3551) +- Added protected virtual method `NetworkTransport.GetDisconnectEventMessage` that, when overridden, a `NetworkTransport` derived custom transport can use to include additional, runtime, information in the message and/or also provide a customized extended message for each `NetworkTransport.DisconnectEvents` value that may not be part of the lower-layer transport event notifications. (#3551) ### Fixed @@ -28,7 +28,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Marked `UnityTransport.ConnectionAddressData.ServerEndPoint` as obsolete. It can't work when using hostnames as the server address, and its functionality can easily be replicated using `NetworkEndpoint.Parse`. (#3591) - Optimized `NetworkList` indexer setter to skip operations when the new value equals the existing value, improving performance by avoiding unnecessary list events and network synchronization. (#3587) - Changed `UnityTransport` so that it now handles setting the current disconnect notification type, via internal `UnityTransportNotificationHandler` class, while also providing extended informational messages for each disconnect event type. (#3551) -- Changed `SendTo.NotMe` so that it doesn't include the server identifier in the target group when connected to a live distributed authority session. (#3551) +- Changed `SendTo.NotMe` so that it no longer includes the server identifier in the target group when connected to a live distributed authority session. (#3551) ## [2.5.0] - 2025-08-01 From 83163e5d2b25bf1cf969fe198d0e9b02017deaf2 Mon Sep 17 00:00:00 2001 From: NoelStephensUnity Date: Fri, 15 Aug 2025 15:45:31 -0500 Subject: [PATCH 16/19] update Simplifying the GetDisconnectEventMessage entry. --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 86e9da12f1..9bc623ba2f 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -13,7 +13,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Added `AsNativeArray()` read‑only accessor to `NetworkList` (#3567) - Added disconnection event notification handling capabilities where `NetworkTransport` derived custom transports can set the current disconnect event type (`NetworkTransport.DisconnectEvents`) that, if implemented, will provide more details on why the transport disconnected. (#3551) - Added protected method `NetworkTransport.SetDisconnectEvent` that a `NetworkTransport` derived custom transport can use to provide the disconnect event type that occurred. (#3551) -- Added protected virtual method `NetworkTransport.GetDisconnectEventMessage` that, when overridden, a `NetworkTransport` derived custom transport can use to include additional, runtime, information in the message and/or also provide a customized extended message for each `NetworkTransport.DisconnectEvents` value that may not be part of the lower-layer transport event notifications. (#3551) +- Added protected virtual method `NetworkTransport.GetDisconnectEventMessage` that can be used to provide a customized message for each `NetworkTransport.DisconnectEvents` value that may or may not be part of the event notifications that the lower-layer transport provides. (#3551) ### Fixed From 9d81870916092cf304d6d837ac151c75bf5facc0 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Wed, 27 Aug 2025 23:26:19 -0500 Subject: [PATCH 17/19] update bumping up to v2.6.0 due to API addition. --- com.unity.netcode.gameobjects/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/package.json b/com.unity.netcode.gameobjects/package.json index f62dfe7be7..b94965e586 100644 --- a/com.unity.netcode.gameobjects/package.json +++ b/com.unity.netcode.gameobjects/package.json @@ -2,7 +2,7 @@ "name": "com.unity.netcode.gameobjects", "displayName": "Netcode for GameObjects", "description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.", - "version": "2.5.1", + "version": "2.6.0", "unity": "6000.0", "dependencies": { "com.unity.nuget.mono-cecil": "1.11.4", From 34a9aedebb21ab81efa767e594a27f761f831933 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Wed, 15 Oct 2025 14:55:05 -0500 Subject: [PATCH 18/19] fix - merge Fixing merge issue. --- .../Runtime/Connection/NetworkConnectionManager.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs index 75e65740a8..ccd506d40b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Connection/NetworkConnectionManager.cs @@ -1440,7 +1440,12 @@ internal void DisconnectClient(ulong clientId, string reason = null) } Transport.ClosingRemoteConnection(); - GenerateDisconnectInformation(clientId, ClientIdToTransportId(clientId), reason); + var transportId = ClientIdToTransportId(clientId); + if (transportId.Item2) + { + GenerateDisconnectInformation(clientId, transportId.Item1, reason); + } + HandleConnectionDisconnect(clientId, reason); } @@ -1487,7 +1492,7 @@ internal void Shutdown() Transport.ShuttingDown(); var clientId = NetworkManager ? NetworkManager.LocalClientId : NetworkManager.ServerClientId; var transportId = ClientIdToTransportId(clientId); - GenerateDisconnectInformation(clientId, transportId, $"{nameof(NetworkConnectionManager)} was shutdown."); + GenerateDisconnectInformation(clientId, transportId.Item1, $"{nameof(NetworkConnectionManager)} was shutdown."); } if (LocalClient.IsServer) From 305838a775172b6fb09b7482421a549810db1f66 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Wed, 15 Oct 2025 16:30:24 -0500 Subject: [PATCH 19/19] test - image version Seeing if reverting back to an earlier version resolves our MSBUILD issue. --- .yamato/project.metafile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.yamato/project.metafile b/.yamato/project.metafile index 10d3ecd736..cc1b6dbe2c 100644 --- a/.yamato/project.metafile +++ b/.yamato/project.metafile @@ -38,13 +38,13 @@ test_platforms: default: - name: ubuntu type: Unity::VM - image: package-ci/ubuntu-22.04:v4 + image: package-ci/ubuntu-22.04:v4.77.0 flavor: b1.large standalone: StandaloneLinux64 desktop: - name: ubuntu type: Unity::VM - image: package-ci/ubuntu-22.04:v4 + image: package-ci/ubuntu-22.04:v4.77.0 flavor: b1.large smaller_flavor: b1.medium standalone: StandaloneLinux64