Unity Transport Upgrade from 1.4.1 to 2.1.0 Causing Client Connection Failures

Project Overview:

  • My Unity project functions correctly using Unity Transport 1.4.1.
  • The project uses Unity Netcode for GameObjects (NGO) for multiplayer functionality.
  • The project involves a client connecting to a server managed via Unity Matchmaker and Multiplay.

Problem: After upgrading Unity Transport from 1.4.1 to 2.1.0, the client fails to connect to the server. All other aspects of the project remain unchanged.

Detailed Logs and Error Message: see below

Steps Taken:

  1. Updated Unity Transport Package: Upgraded from version 1.4.1 to 2.1.0.
  2. Maintained Existing Codebase: Ensured all other code remained unchanged.
  3. Verified Matchmaker and Multiplay Integration: Ensured Matchmaker and Multiplay services are working correctly.

Scripts: MatchmakerClient.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Services.Authentication;
using Unity.Services.Core;
using UnityEngine;
using Unity.Services.Matchmaker;
using Unity.Services.Matchmaker.Models;
using StatusOptions = Unity.Services.Matchmaker.Models.MultiplayAssignment.StatusOptions;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;

#if UNITY_EDITOR
using ParrelSync;
#endif

public class MatchmakerClient : MonoBehaviour
{
    private string _ticketId;

    private async void Start()
    {
        await InitializeUnityServices();
    }

    private async Task InitializeUnityServices()
    {
        var options = new InitializationOptions();
#if UNITY_EDITOR
        string profileName = "QuartetsPlayer" + GetCloneNumberSuffix();
        options.SetProfile(profileName);
#endif
        await UnityServices.InitializeAsync(options);
        await AuthenticationService.Instance.SignInAnonymouslyAsync();
        Debug.Log($"Signed In Anonymously as {AuthenticationService.Instance.PlayerId}");
    }

    public void StartClient()
    {
        CreateATicket();
    }

    private async void CreateATicket()
    {
        var options = new CreateTicketOptions(queueName: "transportqueue");
        var players = new List<Player>
        {
            new Player(AuthenticationService.Instance.PlayerId, null)
        };

        try
        {
            var ticketResponse = await MatchmakerService.Instance.CreateTicketAsync(players, options);
            _ticketId = ticketResponse.Id;
            Debug.Log($"Ticket ID: {_ticketId}");
            PollTicketStatus();
        }
        catch (Exception e)
        {
            Debug.LogError($"Failed to create a matchmaking ticket: {e.Message}");
        }
    }

    private async void PollTicketStatus()
    {
        MultiplayAssignment multiplayAssignment = null;
        bool gotAssignment = false;
        do
        {
            await Task.Delay(TimeSpan.FromSeconds(1f));
            var ticketStatus = await MatchmakerService.Instance.GetTicketAsync(_ticketId);
            if (ticketStatus == null) continue;
            if (ticketStatus.Type == typeof(MultiplayAssignment))
            {
                multiplayAssignment = ticketStatus.Value as MultiplayAssignment;
            }
            switch (multiplayAssignment.Status)
            {
                case StatusOptions.Found:
                    gotAssignment = true;
                    TicketAssigned(multiplayAssignment);
                    break;
                case StatusOptions.InProgress:
                    break;
                case StatusOptions.Failed:
                    gotAssignment = true;
                    Debug.LogError($"Failed to get ticket Status. Error: {multiplayAssignment.Message}");
                    break;
                case StatusOptions.Timeout:
                    gotAssignment = true;
                    Debug.LogError("Failed to get ticket Status. Ticket timed out");
                    break;
                default:
                    throw new InvalidOperationException();
            }
        } while (!gotAssignment);
    }

    private void TicketAssigned(MultiplayAssignment assignment)
    {
        Debug.Log($"Ticket Assigned: {assignment.Ip}:{assignment.Port}");
        
        // Adding a delay before attempting to connect to allow the server to start up
        StartCoroutine(DelayedConnect(assignment.Ip, (ushort)assignment.Port));
    }

    private IEnumerator DelayedConnect(string ip, ushort port)
    {
        Debug.Log($"Waiting before connecting to server at {ip}:{port}...");
        yield return new WaitForSeconds(20); // Adjust the delay as needed

        var transport = NetworkManager.Singleton.GetComponent<UnityTransport>();
        Debug.Log($"Setting connection data: {ip}:{port}");
        transport.SetConnectionData(ip, port);

        Debug.Log("Attempting to start client and connect to the server...");
        NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
        NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnected;

        try
        {
            NetworkManager.Singleton.StartClient();
        }
        catch (Exception ex)
        {
            Debug.LogError($"Exception when starting client: {ex.Message}");
        }
    }

    private void OnClientConnected(ulong clientId)
    {
        Debug.Log($"Client connected successfully with ClientId: {clientId}");
        // Add more detailed logging or handling as needed
    }

    private void OnClientDisconnected(ulong clientId)
    {
        Debug.LogError($"Client disconnected with ClientId: {clientId}");
        // Add more detailed logging or handling as needed
    }

#if UNITY_EDITOR
    private string GetCloneNumberSuffix()
    {
        string projectPath = ClonesManager.GetCurrentProjectPath();
        int lastUnderscore = projectPath.LastIndexOf("_");
        string projectCloneSuffix = projectPath.Substring(lastUnderscore + 1);
        if (projectCloneSuffix.Length != 1)
            projectCloneSuffix = "";
        return projectCloneSuffix;
    }
#endif
}

Observed Behavior:

  • The client receives the assigned server IP and port from the Matchmaker.
  • Attempts to connect to the server result in a “Failed to connect to server” error.
  • Detailed logging suggests the connection is failing at the Unity Transport layer.

Questions:

  1. Is there a known issue or specific configuration required for Unity Transport 2.1.0 to work with Unity Netcode for GameObjects?
  2. Has anyone experienced similar issues when upgrading Unity Transport to 2.1.0, and how did you resolve them?
  3. Are there additional diagnostic steps or logs I can provide to better understand the root cause of this issue?

Any insights, suggestions, or guidance would be greatly appreciated. Thank you!

Detailed Logs and Error Message:

Signed In Anonymously as zgXkwxThahqoI5C3S4xVDYHkThcP
UnityEngine.Debug:Log (object)
MatchmakerClient/<InitializeUnityServices>d__2:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:36)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder:SetResult ()
Unity.Services.Authentication.AuthenticationServiceInternal/<HandleSignInRequestAsync>d__140:MoveNext () (at ./Library/PackageCache/com.unity.services.authentication@2.7.4/Runtime/AuthenticationServiceInternal.cs:806)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Authentication.SignInResponse>:SetResult (Unity.Services.Authentication.SignInResponse)
Unity.Services.Authentication.WebRequest/<SendAsync>d__15`1<Unity.Services.Authentication.SignInResponse>:MoveNext () (at ./Library/PackageCache/com.unity.services.authentication@2.7.4/Runtime/Network/WebRequest.cs:66)
System.Threading.Tasks.TaskCompletionSource`1<string>:SetResult (string)
Unity.Services.Authentication.WebRequest:RequestCompleted (System.Threading.Tasks.TaskCompletionSource`1<string>,long,bool,bool,string,string,System.Collections.Generic.IDictionary`2<string, string>) (at ./Library/PackageCache/com.unity.services.authentication@2.7.4/Runtime/Network/WebRequest.cs:198)
Unity.Services.Authentication.WebRequest/<>c__DisplayClass16_1:<SendAttemptAsync>b__0 (UnityEngine.AsyncOperation) (at ./Library/PackageCache/com.unity.services.authentication@2.7.4/Runtime/Network/WebRequest.cs:76)
UnityEngine.AsyncOperation:InvokeCompletionEvent ()

Ticket ID: e3ff3b17-47c6-49f5-9d6c-bd12f784cd64
UnityEngine.Debug:Log (object)
MatchmakerClient/<CreateATicket>d__4:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:56)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Models.CreateTicketResponse>:SetResult (Unity.Services.Matchmaker.Models.CreateTicketResponse)
Unity.Services.Matchmaker.WrappedMatchmakerService/<CreateTicketAsync>d__8:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/SDK/WrappedMatchmakerService.cs:115)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.CreateTicketResponse>>:SetResult (Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.CreateTicketResponse>)
Unity.Services.Matchmaker.WrappedMatchmakerService/<TryCatchRequest>d__17`2<Unity.Services.Matchmaker.Tickets.CreateTicketRequest, Unity.Services.Matchmaker.Models.CreateTicketResponse>:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/SDK/WrappedMatchmakerService.cs:320)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.CreateTicketResponse>>:SetResult (Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.CreateTicketResponse>)
Unity.Services.Matchmaker.Apis.Tickets.TicketsApiClient/<CreateTicketAsync>d__7:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Apis/TicketsApi.cs:123)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<MakeRequestAsync>d__1:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:41)
System.Runtime.CompilerServices.AsyncTaskCompletionSource`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<CreateWebRequestAsync>d__3:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:56)
System.Runtime.CompilerServices.AsyncTaskCompletionSource`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<CreateHttpClientResponse>d__4:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:84)
System.Runtime.CompilerServices.AsyncTaskCompletionSource`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<>c__DisplayClass4_0/<<CreateHttpClientResponse>b__0>d:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:81)
System.Threading.Tasks.TaskCompletionSource`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.UnityWebRequestHelpers/<>c__DisplayClass0_0:<GetAwaiter>b__0 (UnityEngine.AsyncOperation) (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/UnityWebRequestHelpers.cs:34)
UnityEngine.AsyncOperation:InvokeCompletionEvent ()

Ticket Assigned: 35.246.249.226:9200
UnityEngine.Debug:Log (object)
MatchmakerClient:TicketAssigned (Unity.Services.Matchmaker.Models.MultiplayAssignment) (at Assets/scripts/MatchmaklerClient.cs:102)
MatchmakerClient/<PollTicketStatus>d__5:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:82)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>:SetResult (Unity.Services.Matchmaker.Models.TicketStatusResponse)
Unity.Services.Matchmaker.WrappedMatchmakerService/<GetTicketAsync>d__10:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/SDK/WrappedMatchmakerService.cs:144)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>:SetResult (Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>)
Unity.Services.Matchmaker.WrappedMatchmakerService/<TryCatchRequest>d__17`2<Unity.Services.Matchmaker.Tickets.GetTicketStatusRequest, Unity.Services.Matchmaker.Models.TicketStatusResponse>:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/SDK/WrappedMatchmakerService.cs:320)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>:SetResult (Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>)
Unity.Services.Matchmaker.Apis.Tickets.TicketsApiClient/<GetTicketStatusAsync>d__9:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Apis/TicketsApi.cs:177)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<MakeRequestAsync>d__1:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:41)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<CreateWebRequestAsync>d__3:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:56)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<CreateHttpClientResponse>d__4:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:84)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<>c__DisplayClass4_0/<<CreateHttpClientResponse>b__0>d:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:81)
System.Threading.Tasks.TaskCompletionSource`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.UnityWebRequestHelpers/<>c__DisplayClass0_0:<GetAwaiter>b__0 (UnityEngine.AsyncOperation) (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/UnityWebRequestHelpers.cs:34)
UnityEngine.AsyncOperation:InvokeCompletionEvent ()

Waiting before connecting to server at 35.246.249.226:9200...
UnityEngine.Debug:Log (object)
MatchmakerClient/<DelayedConnect>d__7:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:110)
UnityEngine.MonoBehaviour:StartCoroutine (System.Collections.IEnumerator)
MatchmakerClient:TicketAssigned (Unity.Services.Matchmaker.Models.MultiplayAssignment) (at Assets/scripts/MatchmaklerClient.cs:105)
MatchmakerClient/<PollTicketStatus>d__5:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:82)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>:SetResult (Unity.Services.Matchmaker.Models.TicketStatusResponse)
Unity.Services.Matchmaker.WrappedMatchmakerService/<GetTicketAsync>d__10:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/SDK/WrappedMatchmakerService.cs:144)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>:SetResult (Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>)
Unity.Services.Matchmaker.WrappedMatchmakerService/<TryCatchRequest>d__17`2<Unity.Services.Matchmaker.Tickets.GetTicketStatusRequest, Unity.Services.Matchmaker.Models.TicketStatusResponse>:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/SDK/WrappedMatchmakerService.cs:320)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>:SetResult (Unity.Services.Matchmaker.Response`1<Unity.Services.Matchmaker.Models.TicketStatusResponse>)
Unity.Services.Matchmaker.Apis.Tickets.TicketsApiClient/<GetTicketStatusAsync>d__9:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Apis/TicketsApi.cs:177)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<MakeRequestAsync>d__1:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:41)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<CreateWebRequestAsync>d__3:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:56)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<CreateHttpClientResponse>d__4:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:84)
System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.HttpClient/<>c__DisplayClass4_0/<<CreateHttpClientResponse>b__0>d:MoveNext () (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/HttpClient.cs:81)
System.Threading.Tasks.TaskCompletionSource`1<Unity.Services.Matchmaker.Http.HttpClientResponse>:SetResult (Unity.Services.Matchmaker.Http.HttpClientResponse)
Unity.Services.Matchmaker.Http.UnityWebRequestHelpers/<>c__DisplayClass0_0:<GetAwaiter>b__0 (UnityEngine.AsyncOperation) (at ./Library/PackageCache/com.unity.services.matchmaker@1.1.4/Runtime/Http/UnityWebRequestHelpers.cs:34)
UnityEngine.AsyncOperation:InvokeCompletionEvent ()

Setting connection data: 35.246.249.226:9200
UnityEngine.Debug:Log (object)
MatchmakerClient/<DelayedConnect>d__7:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:114)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)

Attempting to start client and connect to the server...
UnityEngine.Debug:Log (object)
MatchmakerClient/<DelayedConnect>d__7:MoveNext () (at Assets/scripts/MatchmaklerClient.cs:117)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)

Failed to connect to server.
UnityEngine.Debug:LogError (object)
Unity.Netcode.Transports.UTP.UnityTransport:ProcessEvent () (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.9.1/Runtime/Transports/UTP/UnityTransport.cs:889)
Unity.Netcode.Transports.UTP.UnityTransport:Update () (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.9.1/Runtime/Transports/UTP/UnityTransport.cs:938)