diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index b5c96378a7..f007ab7831 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -11,6 +11,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added +- IPv6 is now supported for direct connections when using `UnityTransport`. (#2232) - Added WebSocket support when using UTP 2.0 with `UseWebSockets` property in the `UnityTransport` component of the `NetworkManager` allowing to pick WebSockets for communication. When building for WebGL, this selection happens automatically. (#2201) ### Changed diff --git a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs index 68862254fb..dbbd8dd0c4 100644 --- a/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs +++ b/com.unity.netcode.gameobjects/Runtime/Transports/UTP/UnityTransport.cs @@ -296,10 +296,12 @@ public struct ConnectionAddressData private static NetworkEndpoint ParseNetworkEndpoint(string ip, ushort port) { - if (!NetworkEndpoint.TryParse(ip, port, out var endpoint)) + NetworkEndpoint endpoint = default; + + if (!NetworkEndpoint.TryParse(ip, port, out endpoint, NetworkFamily.Ipv4) && + !NetworkEndpoint.TryParse(ip, port, out endpoint, NetworkFamily.Ipv6)) { Debug.LogError($"Invalid network endpoint: {ip}:{port}."); - return default; } return endpoint; @@ -491,7 +493,8 @@ private bool ClientBindAndConnect() InitDriver(); - int result = m_Driver.Bind(NetworkEndpoint.AnyIpv4); + var bindEndpoint = serverEndpoint.Family == NetworkFamily.Ipv6 ? NetworkEndpoint.AnyIpv6 : NetworkEndpoint.AnyIpv4; + int result = m_Driver.Bind(bindEndpoint); if (result != 0) { Debug.LogError("Client failed to bind"); @@ -632,7 +635,7 @@ 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 + /// The remote IP address (despite the name, can be an IPv6 address) /// The remote port /// The local listen address public void SetConnectionData(string ipv4Address, ushort port, string listenAddress = null) diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs index c26cc81b61..fa53588973 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Transports/UnityTransportTests.cs @@ -7,9 +7,9 @@ namespace Unity.Netcode.EditorTests { public class UnityTransportTests { - // Check that starting a server doesn't immediately result in faulted tasks. + // Check that starting an IPv4 server succeeds. [Test] - public void UnityTransport_BasicInitServer() + public void UnityTransport_BasicInitServer_IPv4() { UnityTransport transport = new GameObject().AddComponent(); transport.Initialize(); @@ -19,9 +19,9 @@ public void UnityTransport_BasicInitServer() transport.Shutdown(); } - // Check that starting a client doesn't immediately result in faulted tasks. + // Check that starting an IPv4 client succeeds. [Test] - public void UnityTransport_BasicInitClient() + public void UnityTransport_BasicInitClient_IPv4() { UnityTransport transport = new GameObject().AddComponent(); transport.Initialize(); @@ -31,6 +31,32 @@ public void UnityTransport_BasicInitClient() transport.Shutdown(); } + // Check that starting an IPv6 server succeeds. + [Test] + public void UnityTransport_BasicInitServer_IPv6() + { + UnityTransport transport = new GameObject().AddComponent(); + transport.Initialize(); + transport.SetConnectionData("::1", 7777); + + Assert.True(transport.StartServer()); + + transport.Shutdown(); + } + + // Check that starting an IPv6 client succeeds. + [Test] + public void UnityTransport_BasicInitClient_IPv6() + { + UnityTransport transport = new GameObject().AddComponent(); + transport.Initialize(); + transport.SetConnectionData("::1", 7777); + + Assert.True(transport.StartClient()); + + transport.Shutdown(); + } + // Check that we can't restart a server. [Test] public void UnityTransport_NoRestartServer() diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTestHelpers.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTestHelpers.cs index 31add35154..f6d73f94ed 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTestHelpers.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTestHelpers.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; using Unity.Netcode.Transports.UTP; +using Unity.Networking.Transport; using UnityEngine; namespace Unity.Netcode.RuntimeTests @@ -37,15 +38,22 @@ public static IEnumerator WaitForNetworkEvent(NetworkEvent type, List events, - int maxPayloadSize = UnityTransport.InitialMaxPayloadSize, int maxSendQueueSize = 0) + int maxPayloadSize = UnityTransport.InitialMaxPayloadSize, int maxSendQueueSize = 0, NetworkFamily family = NetworkFamily.Ipv4) { var logger = new TransportEventLogger(); events = logger.Events; transport = new GameObject().AddComponent(); + transport.OnTransportEvent += logger.HandleEvent; transport.MaxPayloadSize = maxPayloadSize; transport.MaxSendQueueSize = maxSendQueueSize; + + if (family == NetworkFamily.Ipv6) + { + transport.SetConnectionData("::1", 7777); + } + transport.Initialize(); } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs index b08e49eb6b..53fccb0229 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/Transports/UnityTransportTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using Unity.Netcode.Transports.UTP; +using Unity.Networking.Transport; using UnityEngine; using UnityEngine.TestTools; using static Unity.Netcode.RuntimeTests.UnityTransportTestHelpers; @@ -21,6 +22,15 @@ public class UnityTransportTests NetworkDelivery.Reliable }; + private static readonly NetworkFamily[] k_NetworkFamiltyParameters = + { + NetworkFamily.Ipv4, +#if !(UNITY_SWITCH || UNITY_PS4 || UNITY_PS5) + // IPv6 is not supported on Switch, PS4, and PS5. + NetworkFamily.Ipv6 +#endif + }; + private UnityTransport m_Server, m_Client1, m_Client2; private List m_ServerEvents, m_Client1Events, m_Client2Events; @@ -60,10 +70,12 @@ public IEnumerator Cleanup() // Check if can make a simple data exchange. [UnityTest] - public IEnumerator PingPong([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) + public IEnumerator PingPong( + [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, + [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); + InitializeTransport(out m_Server, out m_ServerEvents, family: family); + InitializeTransport(out m_Client1, out m_Client1Events, family: family); m_Server.StartServer(); m_Client1.StartClient(); @@ -89,10 +101,12 @@ public IEnumerator PingPong([ValueSource("k_DeliveryParameters")] NetworkDeliver // Check if can make a simple data exchange (both ways at a time). [UnityTest] - public IEnumerator PingPongSimultaneous([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) + public IEnumerator PingPongSimultaneous( + [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, + [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); + InitializeTransport(out m_Server, out m_ServerEvents, family: family); + InitializeTransport(out m_Client1, out m_Client1Events, family: family); m_Server.StartServer(); m_Client1.StartClient(); @@ -126,13 +140,15 @@ public IEnumerator PingPongSimultaneous([ValueSource("k_DeliveryParameters")] Ne // loopback traffic are too small for the amount of data sent in a single update here. [UnityTest] [UnityPlatform(exclude = new[] { RuntimePlatform.Switch, RuntimePlatform.PS4, RuntimePlatform.PS5 })] - public IEnumerator SendMaximumPayloadSize([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) + public IEnumerator SendMaximumPayloadSize( + [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, + [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) { // We want something that's over the old limit of ~44KB for reliable payloads. var payloadSize = 64 * 1024; - InitializeTransport(out m_Server, out m_ServerEvents, payloadSize); - InitializeTransport(out m_Client1, out m_Client1Events, payloadSize); + InitializeTransport(out m_Server, out m_ServerEvents, payloadSize, family: family); + InitializeTransport(out m_Client1, out m_Client1Events, payloadSize, family: family); m_Server.StartServer(); m_Client1.StartClient(); @@ -164,10 +180,12 @@ public IEnumerator SendMaximumPayloadSize([ValueSource("k_DeliveryParameters")] // Check making multiple sends to a client in a single frame. [UnityTest] - public IEnumerator MultipleSendsSingleFrame([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) + public IEnumerator MultipleSendsSingleFrame( + [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, + [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); + InitializeTransport(out m_Server, out m_ServerEvents, family: family); + InitializeTransport(out m_Client1, out m_Client1Events, family: family); m_Server.StartServer(); m_Client1.StartClient(); @@ -193,11 +211,13 @@ public IEnumerator MultipleSendsSingleFrame([ValueSource("k_DeliveryParameters") // Check sending data to multiple clients. [UnityTest] - public IEnumerator SendMultipleClients([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) + public IEnumerator SendMultipleClients( + [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, + [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - InitializeTransport(out m_Client2, out m_Client2Events); + InitializeTransport(out m_Server, out m_ServerEvents, family: family); + InitializeTransport(out m_Client1, out m_Client1Events, family: family); + InitializeTransport(out m_Client2, out m_Client2Events, family: family); m_Server.StartServer(); m_Client1.StartClient(); @@ -234,11 +254,13 @@ public IEnumerator SendMultipleClients([ValueSource("k_DeliveryParameters")] Net // Check receiving data from multiple clients. [UnityTest] - public IEnumerator ReceiveMultipleClients([ValueSource("k_DeliveryParameters")] NetworkDelivery delivery) + public IEnumerator ReceiveMultipleClients( + [ValueSource("k_DeliveryParameters")] NetworkDelivery delivery, + [ValueSource("k_NetworkFamiltyParameters")] NetworkFamily family) { - InitializeTransport(out m_Server, out m_ServerEvents); - InitializeTransport(out m_Client1, out m_Client1Events); - InitializeTransport(out m_Client2, out m_Client2Events); + InitializeTransport(out m_Server, out m_ServerEvents, family: family); + InitializeTransport(out m_Client1, out m_Client1Events, family: family); + InitializeTransport(out m_Client2, out m_Client2Events, family: family); m_Server.StartServer(); m_Client1.StartClient();