简单的C#脚本

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using Unity.Netcode;
using UnityEngine;
using Unity.Services.Relay;
using Unity.Services.Relay.Models;

public class RelayHandler : MonoBehaviour
{
    [SerializeField]
    [Tooltip("客户端将允许与之通信的最大连接数。分配服务也使用这个值来寻找一个有足够容量的中继服务器。")]
    private int m_MaxConnections = 4;
    [SerializeField] 
    [Tooltip("创建中继服务的首选区域。")]
    private string region;
    
    /// <summary>
    /// 获取分配的中继服务并获取JoinCode。
    /// </summary>
    /// <param name="maxConnections">客户端将允许与之通信的最大连接数。分配服务也使用这个值来寻找一个有足够容量的中继服务器</param>
    /// <param name="region">创建中继服务的首选区域</param>
    /// <returns>参考 https://docs.unity.com/relay/SDK/Unity.Services.Relay.Models.htm</returns>
    public static async Task<(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] connectionData, byte[] key, string joinCode)>
        AllocateRelayServerAndGetJoinCode(int maxConnections, string region = null)
    {
        Allocation allocation;
        string createJoinCode;
        try
        {
            allocation = await Relay.Instance.CreateAllocationAsync(maxConnections, region);
        }
        catch (Exception e)
        {
            Debug.LogError($"Relay create allocation request failed {e.Message}");
            throw;
        }

        Debug.Log($"server: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}");
        Debug.Log($"server: {allocation.AllocationId}");

        try
        {
            createJoinCode = await Relay.Instance.GetJoinCodeAsync(allocation.AllocationId);
        }
        catch
        {
            Debug.LogError("Relay create join code request failed");
            throw;
        }

        return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.Key, createJoinCode);
    }

    /// <summary>
    /// 使用 joinCode 加入中继服务。
    /// </summary>
    /// <param name="joinCode">Host 玩家与其他玩家共享的加入代码。</param>
    /// <returns>参考 https://docs.unity.com/relay/SDK/Unity.Services.Relay.Models.htm</returns>
    public static async Task<(string ipv4address, ushort port, byte[] allocationIdBytes, byte[] connectionData, byte[] hostConnectionData, byte[] key)> 
        JoinRelayServerFromJoinCode(string joinCode)
    {
        JoinAllocation allocation;
        try
        {
            allocation = await Relay.Instance.JoinAllocationAsync(joinCode);
        }
        catch
        {
            Debug.LogError("Relay create join code request failed");
            throw;
        }

        Debug.Log($"client: {allocation.ConnectionData[0]} {allocation.ConnectionData[1]}");
        Debug.Log($"host: {allocation.HostConnectionData[0]} {allocation.HostConnectionData[1]}");
        Debug.Log($"client: {allocation.AllocationId}");

        return (allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.ConnectionData, allocation.HostConnectionData, allocation.Key);
    }
    
    /// <summary>
    /// 作为 Host 开始游戏。
    /// </summary>
    public IEnumerator StartAsHost()
    {
        var serverRelayUtilityTask = AllocateRelayServerAndGetJoinCode(m_MaxConnections, region);
        while (!serverRelayUtilityTask.IsCompleted)
        {
            yield return null;
        }
        if (serverRelayUtilityTask.IsFaulted)
        {
            Debug.LogError("Exception thrown when attempting to start Relay Server. Server not started. Exception: " + serverRelayUtilityTask.Exception.Message);
            yield break;
        }

        var (ipv4address, port, allocationIdBytes, connectionData, key, joinCode) = serverRelayUtilityTask.Result;
        // Todo:向用户显示joinCode。

        // 当启动一个中继服务器时,两个实例的连接数据是相同的。
        NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(ipv4address, port, allocationIdBytes, key, connectionData);
        NetworkManager.Singleton.StartHost();
        yield return null;
    }
    
    /// <summary>
    /// 作为 Client 开始游戏。
    /// </summary>
    /// <param name="relayJoinCode">Host 玩家与其他玩家共享的加入代码。</param>
    public IEnumerator StartAsClient(string relayJoinCode)
    {
        // Todo:通过用户界面获取RelayJoinCode
        var clientRelayUtilityTask = JoinRelayServerFromJoinCode(relayJoinCode);

        while (!clientRelayUtilityTask.IsCompleted)
        {
            yield return null;
        }

        if (clientRelayUtilityTask.IsFaulted)
        {
            Debug.LogError("Exception thrown when attempting to connect to Relay Server. Exception: " + clientRelayUtilityTask.Exception.Message);
            yield break;
        }

        var (ipv4address, port, allocationIdBytes, connectionData, hostConnectionData, key) = clientRelayUtilityTask.Result;

        // 当作为客户端连接到中继服务器时,connectionData和hostConnectionData是不同的。
        NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(ipv4address, port, allocationIdBytes, key, connectionData, hostConnectionData);

        NetworkManager.Singleton.StartClient();
        yield return null;
    }
}