From e03fe074db6a5698e3916d3149d34d202560e37f Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Thu, 22 Oct 2026 11:28:14 -0400 Subject: [PATCH] feat: Improve error message on connection failure --- .../Runtime/Transports/UTP/UnityTransport.cs | 36 ++++++++++++++++++- .../Connection/ClientOnlyConnectionTests.cs | 3 +- 2 files changed, 37 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 f8ce9d815c..1e23226161 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -1144,7 +1144,7 @@ private bool ProcessEvent() // means a clean disconnect that doesn't require logging. if (!m_Driver.Listening && m_ServerClientId == default) { - Debug.LogError("Failed to connect to server."); + LogClientConnectionFailureMessage(); } // Set the disconnect event error code @@ -1172,6 +1172,40 @@ private bool ProcessEvent() return false; } + private void LogClientConnectionFailureMessage() + { + if (OnCurrentTopology() == NetworkTopologyTypes.ClientServer) + { + var reasons = new List { "Server/host is not running." }; + + if (m_ProtocolType == ProtocolType.RelayUnityTransport && !m_UseWebSockets) + { + reasons.Add("Relay port might be blocked on your network. Try using WebSockets."); + if (m_RelayServerData.IsSecure != 0) + { + reasons.Add("DTLS might be blocked on your network. Try using UDP or WebSockets."); + } + } + else if (m_ProtocolType != ProtocolType.RelayUnityTransport) + { + reasons.Add($"Server/host might not be reachable. Try \"ping {ConnectionData.Address}\" in a terminal."); + reasons.Add("The firewall on the server/host might be blocking the connection attempts."); + if (m_UseEncryption && !m_UseWebSockets) + { + reasons.Add("DTLS might be blocked on your network. Try using WebSockets."); + } + } + + const string prefix = "\n\t- "; + Debug.LogError("Failed to connect to server. Possible reasons:" + prefix + string.Join(prefix, reasons)); + } + else + { + // If using DA the SDK should have logged an actual useful error. + Debug.LogError("Failed to connect to server."); + } + } + /// /// Handles accepting new connections and processing transport events. /// diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs index 549f0d8d23..7e0dfb997d 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Connection/ClientOnlyConnectionTests.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Text.RegularExpressions; using NUnit.Framework; using Unity.Netcode.TestHelpers.Runtime; using Unity.Netcode.Transports.UTP; @@ -48,7 +49,7 @@ public IEnumerator ClientFailsToConnect() m_ClientNetworkManager.StartClient(); // Unity Transport throws an error when it times out - LogAssert.Expect(LogType.Error, "Failed to connect to server."); + LogAssert.Expect(LogType.Error, new Regex("^Failed to connect to server\\.")); yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => m_WasDisconnected, m_TimeoutHelper); Assert.False(m_TimeoutHelper.TimedOut, "Timed out waiting for client to timeout waiting to connect!");