游戏大厅示例
注意:此示例使用 PC 版和 Mac 版 Unity 2020.3 进行了测试。
此示例展示了如何使用 Lobby 和 Relay 软件包来创建典型的游戏大厅体验。它还包含 Vivox 语音聊天功能。玩家可以创建大厅,而其他玩家可以通过公开大厅列表或大厅代码加入大厅,然后通过 Relay 建立连接来使用 Unity Transport(简称“UTP”)进行基本的玩家间实时通信。通过 Relay,玩家可以在保持匿名的同时安全地互相通信。只要存在音频输入设备,连接到大厅时也会连接到 Vivox 以启用语音聊天。
注意:这并非“拖放式”解决方案,游戏大厅示例并非计划整个复制到完整项目中的小段代码示例,而是用于演示如何在具备一些基本游戏逻辑和基础架构的垂直切片中使用多项服务。您可以将它作为参考和起点,以了解 Lobby 和 Relay 如何协同工作,以及如何将它们集成到您的项目中。
功能
- Auth 匿名登录:在没有永久帐户的情况下跟踪玩家凭据。
- 大厅创建:玩家创建大厅,以供其他玩家加入。
- 大厅查询:使用过滤条件在大厅列表中查找,或者使用大厅代码。
- 中继遮蔽:大厅中的玩家使用匿名 IP 进行连接。
- UTP 通信:玩家向大厅成员实时发送基本数据。
- Lobby + Relay 连接管理:这两项服务一起自动处理新连接和断开连接。
- Vivox 语音:为大厅创建语音频道,以支持语音通信并向每位用户提供音量控制和静音选项。
以下视频将向您演示如何使用 Lobby 和 Relay 来设置全局配对:
服务组织设置
要使用 Unity Multiplayer 服务,您需要为项目设置云组织 ID。如果您目前没有,请按照如何创建新组织 (How do I create a new Organization?) 文章来设置您的云组织。
获得 ID 后,在 Edit(编辑)> Project Settings(项目设置)> **Services(服务)**下将其与您的项目关联,然后使用 Unity Dashboard(Unity 后台)来管理项目的各种服务。
服务概述
Lobby
通过 Lobby 服务,开发者可以在实时网络连接建立之前创建大厅并在玩家之间共享数据。它简化了将用户连接到 Relay 等其他服务的第一步,并提供了工具,允许玩家查找其他大厅。
这个 Lobby 文档包含代码示例以及该服务的其他信息,其中包括有关如何将 Lobby 与其他代码示例搭配使用的完整详情,可以帮助您更好地了解游戏大厅示例。
Lobby 服务可以在 Unity Dashboard(Unity 后台)中进行管理:https://dashboard.unity3d.com/lobby
Relay
Relay 服务采用主机-客户端模型连接玩家,同时会隐藏主机 IP。这样一来,在所实现的网络体验中,各位玩家就像是直接连接一样,同时只与 Relay 本身共享私人信息。
这个 Relay 文档包含代码示例以及该服务的其他信息,其中包括有关如何将 Relay 与其他代码示例搭配使用的完整详情,可以帮助您更好地了解游戏大厅示例。
Relay 服务可以在 Unity Dashboard(Unity 后台)中进行管理:https://dashboard.unity3d.com/relay
在此示例中,连接到大厅后,玩家便会通过 Relay 建立连接来设置 UTP 实时数据传输。Lobby 和 Relay 都依赖 Auth 来获取凭据。该示例使用 Auth 的匿名登录功能为每位玩家创建唯一的半永久凭据,而不需要开发者维护永久帐户。
Vivox
Vivox 服务向玩家提供语音和文本聊天室,以供进行应用内交流。另外,它还支持空间音频和聊天记录等实用功能。
“Vivox 开发者文档”包含有关使用 Vivox 的完整详情以及其他代码样本,可以帮助您更好地了解游戏大厅示例:https://docs.vivox.com/v5/general/unity/5_15_0/en-us/Default.htm
您可以在 Unity Dashboard(Unity 后台)中管理应用的 Vivox 服务:https://dashboard.unity3d.com/vivox
设置
Unity Dashboard(Unity 后台)的 Lobby 和 Relay 部分包含其各自的设置说明。请选择 About & Support(关于与支持)> **Get Started(开始使用)**并按照提供的步骤操作来将相应服务集成到您的项目中。
在设置好这些服务并将您的项目与您的云组织相关联后,在编辑器中打开 mainScene 场景并开始使用游戏大厅示例。
运行示例
您需要两名“玩家”才能演示完整的示例功能。请创建单独的版本来以运行模式与编辑器并排运行。尽管 Auth 会使用机器的注册信息来创建匿名凭据,但编辑器和您的版本会具有不同的凭据,因为它们会创建不同的注册条目。
大厅加入菜单
大厅加入菜单包含大厅列表 UI,该 UI 用作中心,供玩家使用公开大厅列表或大厅代码相互建立连接。
A.公开大厅列表:显示所有未设置为私人的大厅。大厅包含由开发者定义的数据,其可见性可以设置为公开或非公开。Lobby 服务会清理掉所有“僵尸”房间,使它们不会出现在此列表中。对于此示例,该列表中会显示大厅名称和玩家数量,并且不会显示处于“游戏中”状态的大厅。您可以选择一个大厅,然后选择加入。
B.刷新图标:刷新大厅列表。Lobby 服务会对所有 API 请求进行速率限制,以避免滥发行为。在速率限制内的重复刷新尝试将不起作用(约每 1.5 秒一次,详情请参阅速率限制)。
C.过滤条件:将大厅列表设置为仅显示特定颜色的服务器。Lobby 服务可以根据可见性设置为公开的数据来对任何查询进行过滤。对于此示例,玩家可以选择根据颜色进行过滤,其中颜色是由厅主玩家为其大厅设置的。
D.快速加入按钮:加入列表中与您的过滤条件相符的第一个可用大厅。
E.大厅代码字段:为现有大厅输入大厅代码。除了通过公开大厅列表加入之外,所有大厅都可以通过其代码来加入。这样一来,玩家便可以私下分享对大厅的访问权限。
F.大厅密码字段:输入大厅密码来加入受密码保护的大厅。
G.加入:通过从公开大厅列表中进行选择或输入大厅代码来请求加入。失败的请求也受到速率限制,以防止玩家反复按下按钮进行滥发。
H.创建:允许创建新的大厅。玩家只需选择大厅名称以及是否设为私人大厅,然后便会以厅主身份连接到新大厅。
I.玩家名称:显示玩家名称并允许重命名。默认情况下,系统会根据玩家的 Auth 匿名凭据为玩家分配一个名称,但玩家可以更改该名称,更改后新名称会随着玩家的凭据而传播,以确保所有玩家都看到该新名称。
大厅视图
大厅视图 UI 向大厅中的所有玩家显示来自 Lobby 和 Relay 的信息。新玩家加入后,会立即开始与厅主建立连接,然后与其他大厅成员同步表情和状态变化。
A.大厅名称:在创建大厅时设置,并且无法更改。
B.大厅代码:由 Lobby 服务生成的可分享代码。可以在外部将此信息提供给其他玩家,以让他们加入这个大厅。
C.大厅用户:大厅中的玩家。这里会显示玩家的名称、状态和表情;这些数据通过 Relay + UTP 进行同步,因此当玩家进行任何更改时,所有其他连线玩家都会立即看到相应更改。新玩家一旦连接就会收到最新数据。
D.表情: 显示玩家使用的表情,如果用户连接了麦克风,则还会显示语音聊天控件。
E.Vivox 语音控件:单击该音频图标会将对用户静音/取消静音。
F.Relay IP:Relay 生成的匿名服务器 IP。无需向玩家显示此信息,这里显示此信息只是为了表示 Relay 正在运行。
G.Relay 代码:由 Relay 生成并供 Relay 连接期间使用的内部加入代码。无需向玩家显示此信息,这里显示此信息只是为了表示 Relay 正在运行。
H.表情图标:设置玩家的表情并使用 UTP 进行同步。
I.大厅颜色:(仅限厅主)设置大厅颜色,以供在大厅列表中进行过滤。这个通过 Lobby 进行同步,由于 Lobby 查询受到速率限制,因此该更改不会立即对所有玩家可见。请参阅速率限制。
J.就绪:将玩家设置为就绪状态。当所有玩家都就绪后,厅主会开始倒计时,倒计时结束后相应大厅便会进入“游戏中”状态,同时将从公开大厅列表中隐藏。
架构
该游戏大厅示例被设计为多人游戏大厅的垂直切片,因此它包含一些完整游戏制作中可能存在的额外基础架构,以及一些使多个服务能够协同工作的组件。因此,根据您的需求,代码库中并非所有部分都有用。大多数内容都比较清晰易懂,下面提供了一些大概要点:
Auth、Lobby 和 Relay 服务的使用逻辑都封装在它们各自的目录中。出于方便,许多 API 的使用都进行了抽象处理。
- 例如,LobbyAPIInterface 包含对 Lobby API 的实际调用,而 LobbyAsyncRequests 还对这些调用的结果进行了额外处理,同时包含了一些必要的结构,以确保 API 调用时机正确。
- Relay 目录还包含 Unity Transport (UTP) 的使用逻辑,因为它需要传输才能正常运行。
Game 目录包含用于运行示例本身的核心“粘合”类,它代表了一个游戏的简单框架。
- GameManager 包含运行示例所需的所有核心逻辑,用于设置服务和 UI,管理游戏状态,并处理来自其他组件的消息。
- 这里还存在各种其他类,用于维护示例中多个组件的状态,并在服务中远程为示例所需的 Lobby 和 Relay 数据与该数据的结构之间进行接口连接。
Infrastructure 目录包含用于基本任务的类,这些任务与整体功能相关,但不特定于任何服务。
- Locator 模拟服务定位器模式,允许将可能是单例的行为轻松地替换进来和替换出去。
- Messenger 会创建一个简单的消息系统,用于将不相关的类保持解耦,允许它们在相应的事件发生时向任意监听器发送消息。例如,当大厅更新时或玩家与中继断开连接时。
- Observer 模式用于所有 UI 元素以及远程 Lobby 和 Relay 数据的本地副本。每当观察的数据发生变化时,Observer 都会收到通知,而数据的所有者无需知道谁在观察数据。
UI 目录专门包含用于示例 UI 和观察相关数据的逻辑。尽管这些文件展示了 Observer 模式的使用方式,但查看这些文件不应是理解如何使用服务本身的必要条件。
- 有一些文件包含了仅仅实现 ObserverBehaviour 的类。这是因为 Unity 要求 MonoBehaviours 存在于同名的文件中。
- 请注意,许多 UI 通过 CanvasGroup Alpha 来控制可见性,这意味着即使对玩家不可见,一些行为仍然会持续运行。
这里包含多个 Tests 目录,用于演示一些代码的核心行为和边缘情况。特别是,Lobby 和 Relay 的运行模式测试可用于确保您与服务的连接正常工作。
在编辑器中,项目资源被分成嵌套的预制件,以便在示例开发过程中进行更改。尽管一些 UI 元素依赖于序列化的事件处理程序,但其细节并不重要。
注意事项
虽然游戏大厅示例不仅仅代表了 Lobby 和 Relay 服务的最小实现,但它是不全面的,一些设计决策是为了让开发速度更快或更易阅读而做出的。
使用 Lobby 和 Relay 的所有操作都依赖于异步 API 调用。该示例代码包含一些逻辑来处理可能由任意时间接收结果引发的问题,但没有逻辑来处理用户在设置和清理期间发起调用。在进入和退出大厅时进行快速操作可能导致意外行为。
Relay 不支持主机迁移,但 Lobby 支持。如果大厅主机断开连接,对于客户端来说,大厅可能会继续运行,直到 Lobby 检测到断开连接。在实际操作中,您可能需要在数据可能很快失去同步的情况下,实现主机与客户端之间的额外周期性握手。
该示例通过 Lobby 和 Relay 建立心跳 ping,以保持连接活跃,但它们不对大厅的持续时间施加任何限制。实际使用中应考虑最大持续时间,比如最大游戏时长。
HTTP 错误将在控制台中显示。这些错误由 Lobby 和 Relay API 调用因各种原因而返回。一般来说,它们不会影响示例的执行,但由于样本在出现这些错误时不提供任何解释性 UI,因此可能会导致玩家出现意外行为。
当 Lobby 服务以任意顺序处理多个传入的 API 调用时,通常是在离开大厅时,可能会出现 404 (“Not Found”) errors(404“未找到”错误)。另外,尝试加入无效大厅时也会出现该错误,例如当大厅已被删除但因尚未刷新而仍然出现在大厅列表中时。
当速率受限制的操作发生得太快时,会出现 429 (“Too Many Requests”) errors(429“请求过多”错误)。特别是,过快地刷新大厅列表会导致从 QueryLobbiesAsync 调用出现 429 错误。请参阅 Lobby 文档,以了解详细信息。
由于所有 Lobby 和 Relay 操作都需要 Auth 凭据,如果用户在 Auth 登录完成之前进入大厅菜单,则会出现 401 (“Unauthorized”) errors(401“未经授权”错误)。
当玩家尝试使用与另一名玩家相同的凭据加入大厅时,会出现 409 (“Conflict”) errors(409“冲突”错误)。特别是,当您尝试使用多个独立版本进行测试时,便会出现此错误,这是因为这些版本在您的计算机上共享相同的注册表项。要在一台计算机上进行三名或更多玩家的测试,请按照以下步骤操作:
- 创建一个使用符号链接与原始资源和资源包链接的重复项目,以便使用相同的资源。同时复制 ProjectSettings,但不要将它们链接到原始项目。请注意,创建符号链接的过程将取决于您的操作系统。
- 在另一个编辑器中打开此项目。
- 在 Edit(编辑)> Project Settings(项目设置)> **Player(玩家)**下,修改 Product Name(产品名称)。这样一来,重复项目便会拥有新的注册表项,因此 Auth 将会分配新的凭据。
- 验证以运行模式或独立版本形式运行示例时会分配与原始项目不同的默认玩家名称。这表示分配了不同的 Auth 凭据,从而防止出现 409 错误。