From b8dddeaf635aa5ebe8f2d9b5cffe42ba7fa7cdaa Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Thu, 30 Oct 2025 13:27:01 -0400 Subject: [PATCH 1/5] Improve documentation on SetConnectionData --- .../Runtime/Transports/UTP/UnityTransport.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 5b71fcadbe..b296fb2097 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -788,9 +788,9 @@ public void SetClientRelayData(string ipAddress, ushort port, byte[] allocationI /// /// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call /// - /// The remote IP address (despite the name, can be an IPv6 address or a domain name) - /// The remote port - /// The local listen address + /// The remote IP address (despite the name, can be an IPv6 address or a domain name). + /// The remote port to connect to. + /// The address the server is going to listen on. public void SetConnectionData(string ipv4Address, ushort port, string listenAddress = null) { ConnectionData = new ConnectionAddressData @@ -806,8 +806,8 @@ public void SetConnectionData(string ipv4Address, ushort port, string listenAddr /// /// Sets IP and Port information. This will be ignored if using the Unity Relay and you should call /// - /// The remote end point - /// The local listen endpoint + /// The remote endpoint the client should connect to. + /// The endpoint the server should listen on. public void SetConnectionData(NetworkEndpoint endPoint, NetworkEndpoint listenEndPoint = default) { string serverAddress = endPoint.Address.Split(':')[0]; From 1a2dab6e7d6407f8a347611899ca49d4d27ed3e5 Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Thu, 30 Oct 2025 14:02:48 -0400 Subject: [PATCH 2/5] Add possibility of binding clients to a specific port --- .../Runtime/Transports/UTP/UnityTransport.cs | 20 +++++++++++++++++++ .../Editor/Transports/UnityTransportTests.cs | 14 +++++++++++++ 2 files changed, 34 insertions(+) diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index b296fb2097..5b33468c70 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -245,6 +245,12 @@ internal static NetworkEndpoint ParseNetworkEndpoint(string ip, ushort port) return endpoint; } + /// + /// The port the client will bind to. If 0 (the default), an ephemeral port will be used. + /// + [SerializeField] + public ushort ClientBindPort; + /// /// Endpoint (IP address and port) clients will connect to. /// @@ -683,6 +689,20 @@ private bool ClientBindAndConnect() } InitDriver(); + + // Don't bind yet if connecting to a hostname, since we don't know if it will resolve to IPv4 or IPv6. + if (serverEndpoint.Family != NetworkFamily.Invalid && ConnectionData.ClientBindPort != 0) + { + var bindEndpoint = serverEndpoint.Family == NetworkFamily.Ipv6 + ? NetworkEndpoint.AnyIpv6.WithPort(ConnectionData.ClientBindPort) + : NetworkEndpoint.AnyIpv4.WithPort(ConnectionData.ClientBindPort); + if (m_Driver.Bind(bindEndpoint) != 0) + { + Debug.LogError($"Couldn't create socket. Possibly another process is using port {ConnectionData.ClientBindPort}."); + return false; + } + } + Connect(serverEndpoint); return true; diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs index 7afd0b879d..594467efc2 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs @@ -184,6 +184,20 @@ public void UnityTransport_EmptySecurityStringsShouldThrow([Values("", null)] st } } + [Test] + public void UnityTransport_BindClientToSpecificPort() + { + UnityTransport transport = new GameObject().AddComponent(); + transport.Initialize(); + transport.SetConnectionData("127.0.0.1", 4242); + transport.ConnectionData.ClientBindPort = 14242; + + Assert.True(transport.StartClient()); + Assert.AreEqual(14242, transport.GetLocalEndpoint().Port); + + transport.Shutdown(); + } + #if HOSTNAME_RESOLUTION_AVAILABLE private static readonly (string, bool)[] k_HostnameChecks = { From fc81db86e386fa946907b30829e1ee842aa39572 Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Thu, 30 Oct 2025 14:08:43 -0400 Subject: [PATCH 3/5] Don't overwrite the client bind port in SetConnectionData --- .../Runtime/Transports/UTP/UnityTransport.cs | 3 ++- 1 file changed, 2 insertions(+), 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 5b33468c70..2f3c987ab2 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -817,7 +817,8 @@ public void SetConnectionData(string ipv4Address, ushort port, string listenAddr { Address = ipv4Address, Port = port, - ServerListenAddress = listenAddress ?? ipv4Address + ServerListenAddress = listenAddress ?? ipv4Address, + ClientBindPort = ConnectionData.ClientBindPort }; SetProtocol(ProtocolType.UnityTransport); From 5241cb6e18efb25e0a72b1313252b177c879c46c Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Thu, 30 Oct 2025 14:20:41 -0400 Subject: [PATCH 4/5] Add CHANGELOG entry --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 6585a7dc93..d949f4b128 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -10,6 +10,8 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added +- It is now possible to control which port clients will bind to using the `UnityTransport.ConnectionData.ClientBindPort` field. If not set, clients will bind to an ephemeral port (same as before this change). (#3764) + ### Changed From 3c1b0a6d5061c9e5f087c1bab078d91aee4418be Mon Sep 17 00:00:00 2001 From: Simon Lemay Date: Fri, 31 Oct 2025 12:54:31 -0400 Subject: [PATCH 5/5] Bump version to 2.8.0 --- 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 1942f6f429..c0d0083726 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.7.1", + "version": "2.8.0", "unity": "6000.0", "dependencies": { "com.unity.nuget.mono-cecil": "1.11.4",