搭配 Netcode for GameObjects (NGO) 使用 Relay
Netcode for GameObjects (NGO) 是用于 GameObject
和 MonoBehavior
工作流程的 Unity 网络连接功能包,可与 Relay 无缝协作。NGO 框架可与多种底层传输解决方案(包括 Unity Transport Package (UTP))搭配使用。
注意:通过 Relay 服务器执行的绑定或其他交互均通过网络解决方案 UTP 或 NGO 来实现。建议搭配 NGO 使用 Relay,不过您也可以使用其他网络代码库,例如 Mirror 网络 API。请访问搭配 UTP 使用 Relay,了解如何将 Relay 与 UTP 和其他网络代码库配合使用。
配置 Relay SDK
搭配 NGO 使用 Relay 前,必须先配置 Unity 项目。请参阅开始使用 Relay。启用 Relay 服务并通过 Unity 编辑器链接到 Unity Project ID 后,即可导入必需项、设置 NetworkManager
、使用 Unity 服务对玩家进行身份验证以及开始使用 Relay SDK。
设置 Relay SDK 后,配置游戏客户端分别以主机玩家身份和加入玩家身份执行加入 Relay 游戏会话所需的任务。
注意:本文档中的示例使用 NGO 1.1.0。
导入必需项
使用 Relay 服务前,必须导入 Relay SDK 和 UTP 以及其他命名空间。使用从“Packages and SDK Download Center(包和 SDK 下载中心)”生成的代码片段。
导航到 Packages and SDK Download Center(包和 SDK 下载中心)。
选择以下包:
Relay
Netcode for GameObjects
选择 Generate Code Snippet(生成代码片段),然后按说明进行操作。
以下代码示例演示了必需项的导入。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using Unity.Services.Core;
using Unity.Services.Authentication;
using Unity.Services.Relay;
using Unity.Services.Relay.Http;
using Unity.Services.Relay.Models;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using Unity.Networking.Transport;
using Unity.Networking.Transport.Relay;
using NetworkEvent = Unity.Networking.Transport.NetworkEvent;
设置 NetworkManager
从 Unity Dashboard(Unity 后台)安装包后,使用 Unity 编辑器在项目中针对 Relay 和 NGO 设置 NetworkManager
。
注意:如果发现有任何选项缺失,请确认已安装 Unity Dashboard(Unity 后台)的“Install packages(安装包)”中所列的所有包。
- 向场景中添加新的 GameObject。
- 添加 NetworkManager MonoBehavior。
- 在 **MonoBehavior Properties(MonoBehavior 属性)**中,选择 UnityTransport 传输。选择“UnityTransport”之后,组件列表的底部会显示
MonoBehavior
调用的 Unity Transport(脚本)。 - 将新组件的 **Protocol Type(协议类型)**设置为 Relay Unity Transport。
设置变量和实用函数
您还需要初始化一些变量,例如最大连接数和加入代码。
const int m_MaxConnections = 4;
public string RelayJoinCode;
对玩家进行身份验证
主机玩家和连接玩家都必须通过身份验证。对玩家进行身份验证的最简单方法是使用 Authentication 服务的 SignInAnonymouslyAsync()
方法。请参阅如何使用匿名登录和如何使用特定平台登录。
如需更多信息,请参阅关于 Unity Authentication 和 Unity Authentication 用例。
async void Example_AuthenticatingAPlayer()
{
try
{
await UnityServices.InitializeAsync();
await AuthenticationService.Instance.SignInAnonymouslyAsync();
var playerID = AuthenticationService.Instance.PlayerId;
}
catch (Exception e)
{
Debug.Log(e);
}
}
主机玩家
以主机玩家身份启动的游戏客户端必须能够创建分配、请求加入代码、配置连接类型、创建用于绑定到 Relay 服务器的 NetworkDriver
单例实例以及侦听来自加入玩家的连接请求。
警告:如果通过 SetRelayServerData
/SetRelayClientData
提供的信息与从分配获得的信息不匹配,您将无法连接到 Relay 服务器。例如,如果 isSecure
参数不匹配,您将收到“无法连接服务器”错误消息。
要防止此类情况发生,最简单的方法之一就是直接从分配构建 RelayServerData
。不过,您必须使用 Netcode for GameObjects (NGO) 版本 1.1.0 或更高版本。
创建分配并请求加入代码
以下代码片段中包含函数 AllocateRelayServerAndGetJoinCode
,该函数展示了如何使用 Relay SDK 创建分配、请求加入代码以及将连接类型配置为 DTLS。
public static async Task<RelayServerData> AllocateRelayServerAndGetJoinCode(int maxConnections, string region = null)
{
Allocation allocation;
string createJoinCode;
try
{
allocation = await RelayService.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 RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);
}
catch
{
Debug.LogError("Relay create join code request failed");
throw;
}
return new RelayServerData(allocation, "dtls");
}
配置传输并启动 NGO
以下代码片段中包含函数 ConfigureTransportAndStartNgoAsHost
,该函数展示了主机玩家如何使用 Relay SDK 和 NGO SDK 配置传输并启动 NGO。
注意:以主机玩家身份启动 Relay 服务器时,两个连接数据实例是完全相同的。
IEnumerator Example_ConfigureTransportAndStartNgoAsHost()
{
var serverRelayUtilityTask = AllocateRelayServerAndGetJoinCode(m_MaxConnections);
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 relayServerData = serverRelayUtilityTask.Result;
// Display the joinCode to the user.
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(relayServerData);
NetworkManager.Singleton.StartHost();
yield return null;
}
加入玩家
以加入玩家身份启动的游戏客户端必须能够加入分配、配置连接类型、创建用于绑定到 Relay 服务器的 NetworkDriver
单例实例以及向主机玩家发送连接请求。
警告:如果通过 SetRelayServerData
/SetRelayClientData
提供的信息与从分配获得的信息不匹配,您将无法连接到 Relay 服务器。例如,如果 isSecure
参数不匹配,您将收到“无法连接服务器”错误消息。
要防止此类情况发生,最简单的方法之一就是直接从分配构建 RelayServerData
。不过,您必须使用 Netcode for GameObjects (NGO) 版本 1.1.0 或更高版本。
加入分配
以下代码片段中包含函数 JoinRelayServerFromJoinCode
,该函数展示了如何使用 Relay SDK 和加入代码加入分配,以及将连接类型配置为 DTLS。
public static async Task<RelayServerData> JoinRelayServerFromJoinCode(string joinCode)
{
JoinAllocation allocation;
try
{
allocation = await RelayService.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 new RelayServerData(allocation, "dtls");
}
配置传输并以加入玩家身份启动 NGO
以下示例代码演示了加入玩家如何配置传输和启动 Netcode for GameObjects (NGO)。
注意:以加入玩家身份启动 Relay 服务器时,主机玩家和加入玩家各自具有不同的连接数据。
IEnumerator Example_ConfigureTransportAndStartNgoAsConnectingPlayer()
{
// Populate RelayJoinCode beforehand through the UI
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 relayServerData = clientRelayUtilityTask.Result;
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(relayServerData);
NetworkManager.Singleton.StartClient();
yield return null;
}