> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# PlayFab Party 对象及其关系

> 了解核心 PlayFab Party 对象,例如网络、设备、端点和聊天控件,以及它们在实时聊天和数据通信中的相互关系。

要成功利用 PlayFab Party API 的强大功能和灵活性,首先需要了解在其作用域内定义的以下关键对象:

* [**设备**](#device) - 在物理设备上执行的游戏的一个独立实例。只要使用 API,就存在一个本地设备。
* [**用户**](#user) - 单个已登录的玩家,或者更准确地说,是游戏为身份验证和识别目的提供给 PlayFab Party 的 PlayFab `title_player_account` [实体](/services/playfab/live-service-management/game-configuration/entities)。一个或多个用户与给定的设备关联。
* [**网络**](#network) - 游戏为交换聊天或数据通信而创建的一个安全集合,包含一个或多个设备及其授权用户。网络通常与游戏的多人游戏会话或聊天派对概念对齐。
* [**端点**](#endpoint) - 在网络内发送和接收数据的抽象。端点可以代表一个设备、一个用户或任何所需的游戏特定概念。
* [**聊天控件**](#chat-control) - 专门用于在一个或多个网络中配置、发起和定向语音与文字聊天的用户表示。

## 对象关系

作为简化的概念层次结构,[网络](#network)包含[设备](#device),后者又包含[用户](#user)、可选的[端点](#endpoint)和可选的[聊天控件](#chat-control)。例如:

<img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/networking/simplified-party-object-hierarchy.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=89ce170ff66049c4f7569d3f1acb3460" alt="Simplified PlayFab Party object hierarchy" width="479" height="422" data-path="images/playfab/multiplayer/networking/simplified-party-object-hierarchy.png" />

虽然足够简单易懂,但前述关系图实际上是对 PlayFab Party 功能的不完整描绘,单独看可能会产生误导。实际上,Party API 支持设备一次连接到 *多个* 网络。例如,人们可能希望随着时间的推移与一组朋友保持通信,而同一组人也与陌生人一起加入和离开各种更大的游戏会话。考虑这种更广泛的场景可以让我们更好地理解这些对象之间的关系。

将设备概念化为\_属于\_网络可能感觉直观,但事实并非如此。更准确的做法是意识到设备\_参与\_网络。因此,Party 库对于遇到的特定实例,无论其与本地设备共享多少个网络,始终只创建一个设备 API 对象(无论是远程还是本地)。

例如,下图显示了两个网络和三台带用户、聊天控件和端点的设备。 *设备 A* 及其两个聊天控件(与关联的用户)参与 *网络 1*,而 *设备 B* 和 *C* 各自使用一个聊天控件(与关联的用户)同时连接到 *网络 1* *和* *网络 2*。所有设备都在其所连接的每个网络中创建了一或两个端点:

<img src="https://mintcdn.com/microsoft-4404708b/dqv53299jA1M-fNi/images/playfab/multiplayer/networking/party-objects-in-multiple-networks.png?fit=max&auto=format&n=dqv53299jA1M-fNi&q=85&s=e714ccc5a71d813a17fd1e15985773a8" alt="PlayFab Party objects in multiple networks" width="440" height="318" data-path="images/playfab/multiplayer/networking/party-objects-in-multiple-networks.png" />

在图中,每台设备都看到所有三台设备及其聊天控件的单个实例,因为它们彼此之间至少共享一个网络。 *设备 A* 只知道 *网络 1* 中的 *端点 1-4*,但 *设备 B* 和 *C* 也能看到它们在 *网络 2* 中创建的 *端点 5-7*。

如果 *设备 C* 改为仅参与 *网络 2* 而不同时参与这两个网络,则:

* *设备 C* 显然无法在 *网络 1* 中创建 *端点 4*,也看不到 *端点 1-3*。
* *设备 C* 不会知道仅存在于 *网络 1* 中的 *设备 A* 或其两个聊天控件。
* *设备 A* 类似地不会看到仅存在于 *网络 2* 中的 *设备 C* 或其聊天控件。

然而, *设备 B* **仍会**看到所有设备及其聊天控件,因为它仍在两个网络中。

因此,尽管设备和聊天控件与网络之间处于严格的层次树关系“之外”,重要的是要注意游戏实例永远不会真正在没有伴随网络上下文的情况下遇到远程设备或聊天控件。如果本地设备和远程设备或聊天控件至少有一个共同网络,则可能可以看到远程对象。但如果没有共同的网络,则永远不会创建远程对象。

<Note>
  不要求游戏同时连接到多个网络才能成功使用 PlayFab Party。你可以在[后续高级主题](/services/playfab/multiplayer/networking/concepts-multiple-networks)中了解更多关于是否以及如何使用多个网络的信息。
</Note>

## 通用对象属性

所有对象都有明确定义的生命周期。本地游戏实例直接或使用标准化通知机制创建和销毁每个对象,这些通知机制仅在游戏选择的时间窗口期间发出信号。稍后的主题将更详细地描述如何处理通知。

所有 PlayFab Party API 对象也都支持\_自定义上下文\_的概念,这就是一种在对象上存储可选、仅本地的“快捷方式”指针或值的方法。自定义上下文可以轻松地从 PlayFab Party 对象返回到内存中相应的私有游戏对象(如果有),而无需执行低效的查找。这些值不会远程传输,因为指针值只对本地游戏实例有意义。

最后,除[网络](#network)以外的上述所有对象都有一个专用的“Local”子对象,其中包含仅对拥有该对象的本地[设备](#device)可用的方法和属性。

例如,有一个用于表示任何本地或远程[端点](#endpoint)的基类 `PartyEndpoint` 对象,以及一个更特定的 `PartyLocalEndpoint` 对象,只有当端点实际由本地设备创建时,才能通过 `PartyEndpoint::GetLocal()` 检索该对象。这是公开用于传输游戏数据的 `PartyLocalEndpoint::SendMessage()` 方法的地方,因为让一台设备能够以某种方式从另一台远程设备的源端点传输数据是没有意义的。

使用 C++ PlayFab Party 接口(推荐)时,对象作为 C++ 类实例公开。使用平面 C 接口时,对象由句柄值表示。

## 更详细地介绍所有主要对象的角色

1. [管理器](#manager)(`PartyManager`)
2. [网络](#network)(`PartyNetwork`)
3. [设备](#device)(`PartyDevice` 和 `PartyLocalDevice`)
4. [用户](#user)(用户实体 ID 和 `PartyLocalUser`)
5. [端点](#endpoint)(`PartyEndpoint` 和 `PartyLocalEndpoint`)
6. [聊天控件](#chat-control)(`PartyChatControl` 和 `PartyLocalChatControl`)
7. [状态变更](#state-change)(`PartyStateChange`)

### 管理器

除了前面总结的对象之外,PlayFab Party API 还公开了一个顶层的 `PartyManager` 单例对象。

此实用工具/组织对象在很大程度上用作开始使用其他对象的起点。例如,新的[网络](#network)和本地[用户](#user)最初都在管理器中创建。所有异步操作完成和通知也集中在这里。最基本的是,管理器是在使用之前初始化 PlayFab Party 库以及在不再需要时清理该库的地方。

### 网络

`PartyNetwork` 对象表示一个安全的参与[设备](#device)、其授权[用户](#user)以及任何伴随的[端点](#endpoint)或[聊天控件](#chat-control)集合。 *网络* 最初创建时为空,但设备连接到它们并将至少一个本地用户验证到 *网络* 中。没有任何已验证用户的 *网络* 会在超时后自动销毁。

为了连接到它们, *网络* 使用 *网络描述符* 进行引用。 *网络描述符* 主要是包含 PlayFab Party 内部识别和定位 *网络* 所需信息的不透明二进制结构。API 提供了将结构序列化为 Web 服务友好字符串以及反序列化的方法,以便可以使用常见的社交平台邀请机制、[PlayFab Matchmaking](/services/playfab/multiplayer/matchmaking) 或其他 PlayFab Party 本身范围之外的外部会合机制与其他设备交换。

<Note>
  *网络* 的 *网络描述符* 在极少情况下可能会更改。游戏应准备好接收此类更改的通知,并随后为现有 *网络* 更新或重新广告新的 *网络描述符*,以避免其他设备连接时出现问题。
</Note>

即使有 *网络描述符*,对 *网络* 的访问也仅限于已授权用户。此用户授权在 *网络* 创建期间通过后续创建和撤销邀请完成,主题[邀请和安全模型](/services/playfab/multiplayer/networking/concepts-invitations-security-model)对此有更详细的描述。

游戏可以选择使用邀请将进入限制为仅用户的好友,或防止恶意玩家加入 *网络*。

设备可以同时连接到多个 *网络*。你可以在[后续主题](/services/playfab/multiplayer/networking/concepts-multiple-networks)中了解更多关于是否以及如何使用多个 *网络* 的信息。

可对 `PartyNetwork` 对象执行的操作包括:向其中验证本地用户、连接和枚举聊天控件、创建和枚举端点,或获取 *网络* 范围的性能信息。

### 设备

`PartyDevice` 对象代表在物理设备上执行的游戏及其 PlayFab Party 库代码的独立实例。大多数操作并不直接对 `PartyDevice` 对象本身执行;相反,它们是一种组织机制,用于定义哪些[端点](#endpoint)或[聊天控件](#chat-control)属于该游戏实例,特别是对于支持多个本地[用户](#user)同时使用的平台和游戏。例如,PlayFab Party 使用此关系知识来优化游戏数据和聊天的传输,即使设备上的多个目标需要接收消息,也只发送该消息的一个副本。

远程 `PartyDevice` 对象是连接到[网络](#network)并将用户验证到该网络的“副产品”。它们仅在与本地 *设备* 也已连接到的网络中参与的、与该 *设备* 关联的有效已验证远程用户存在时才被创建。相应地,一旦这不再成立,它们也会被销毁。

另一方面,只要 PlayFab Party 处于已初始化状态,本地游戏实例始终可以引用专门的子对象 `PartyLocalDevice`。它永远不会被显式地创建或销毁。

### 用户

PlayFab Party *用户* 是一个独特的人类玩家,游戏为其执行 [PlayFab 玩家登录](/services/playfab/identity/player-identity/login) 以获取 `title_player_account` [实体 ID](/services/playfab/live-service-management/game-configuration/entities) 和令牌。

远程用户在 PlayFab Party API 中仅通过其与[聊天控件](#chat-control)以及(可选地)与[端点](#endpoint)关联的实体 ID 字符串来标识。它们不使用专用对象表示。这是因为除了原始识别和作为与那些其他对象关联的标签之外,PlayFab Party 没有与任意用户以有意义的方式交互的功能。

相反,对于本地 *用户*,存在显式的 `PartyLocalUser` 对象,因为游戏在 PlayFab Party 内拥有其生命周期管理。游戏通常会在使用适用的[登录](/services/playfab/identity/player-identity/login)方法成功登录该 PlayFab 玩家时创建 `PartyLocalUser`,并在该用户注销时适当地销毁 `PartyLocalUser`。对于支持多个本地玩家登录的平台和游戏,应为每位玩家创建额外的 `PartyLocalUser` 对象。

`PartyLocalUser` 对象也很重要,因为它们是所有身份验证的基础。要么创建新的[网络](#network),要么向网络进行身份验证,都必须存在有效的本地 *用户*。

授权用户在主题[邀请和安全模型](/services/playfab/multiplayer/networking/concepts-invitations-security-model)中有更详细的描述。

几乎每个操作都需要提供或存在 `PartyLocalUser`,尽管很少有操作直接在 `PartyLocalUser` 对象本身上执行。

`PartyLocalUser` 对象使用 `PartyManager` 对象创建。它们只能由其创建者显式销毁。虽然它们在远程[设备](#device)上没有直接的对象表示,但如果拥有设备移除 `PartyLocalUser` 或断开与网络的连接(无论是正常还是异常),与其关联的聊天控件和端点将被销毁。

### 端点

`PartyEndpoint` 对象是可选的,但对于利用它们的游戏来说,它们是 PlayFab Party 数据通信的核心。与典型的网络套接字类似, *端点* 是在[网络](#network)内发起或定向数据消息的抽象寻址机制。它们可以代表一个[设备](#device)、单个[用户](#user)或任何你希望唯一标识以发送和接收消息的任意游戏定义概念(例如,一个坦克单位)。

专门的 `PartyLocalEndpoint` 子对象用于本地游戏实例在网络中创建的 *端点*。大部分 *端点* 功能都位于此处。其 `PartyLocalEndpoint::SendMessage()` 将游戏数据负载从 `PartyLocalEndpoint` 传输到同一网络中的一个或多个其他 `PartyEndpoint` 对象。它提供了各种选项,用于选择如何最好地处理 Internet 数据包丢失(例如,保证传输和/或排序)、在低延迟与合并来自同一或其他本地端点的多个消息以降低带宽使用之间控制权衡,以及在连接质量不足以支持游戏发送速率时做出反应。

除了自己是数据消息的源或目标之外,每个 `PartyEndpoint` 对象还由 PlayFab Party 分配一个 16 位 *端点唯一标识符*,允许你在发送到网络内单独 `PartyEndpoint` 对象或从其发送的消息负载中引用特定的 *端点*。例如,这提供了一种便捷的方式,可避免发送完整的、较大的用户[实体 ID](/services/playfab/live-service-management/game-configuration/entities) 字符串或其可能表示的其他标识符的开销,而无需构建自己的点对点身份协议协商。

`PartyLocalEndpoint` 对象使用其所包含的 `PartyNetwork` 对象创建。这样做会导致在远程设备上创建相应的 `PartyEndpoint` 对象。 *端点* 可以由其创建者显式销毁,或者当拥有设备与网络断开连接,或关联的 `PartyLocalUser` 对象(如果指定了)从网络中移除时,被隐式销毁。

### 聊天控件

`PartyChatControl` 对象是用于使用 PlayFab Party 可选聊天通信功能的机制。它们表示特定[用户](#user)的关联音频输入/输出设备、偏好设置和通信策略。

专门的 `PartyLocalChatControl` 子对象也可用于本地游戏实例创建的 *聊天控件*。例如,你在此处配置允许与远程 `PartyChatControl` 对象进行聊天通信的权限,以选择全网络与仅团队聊天,或应用平台策略限制。本地 *聊天控件* 用于发送聊天文字、将文字合成为语音、请求语音流的转录和翻译、静音等。

`PartyLocalChatControl` 对象必须先连接到[网络](#network),然后才会在同一网络中的远程[设备](#device)上创建为 `PartyChatControl` 对象。即使设备和 *聊天控件* 共同连接到多个网络,设备也始终仅看到创建的一个代表性 `PartyChatControl` 对象。这有助于避免不必要地重复或中断音频和文字聊天消息。

`PartyLocalChatControl` 对象使用所包含的 `PartyLocalDevice` 对象创建。 *聊天控件* 可以由其创建者显式销毁,或者当拥有设备与网络断开连接,或关联的 `PartyLocalUser` 对象从网络中移除时,被隐式销毁。

### 状态变更

`PartyStateChange` 结构用于向游戏通知所有异步操作完成、传入消息、更新通知以及其他与 API 相关的事件。

为了简化你处理具有不可预测时序的、通过 Internet 进行的复杂多机交互的方式,PlayFab Party 保证除非游戏显式调用,否则不会修改它从 API 报告的任何状态。但由于你仍需要一种方式来了解修改本地状态的远程发起的操作或计划外事件,PlayFab Party 和游戏通过一对特殊方法 `PartyManager::StartProcessingStateChanges()` 和 `PartyManager::FinishProcessingStateChanges()` 进行协作。这些方法在游戏工作循环的一个便于处理此类更新的地方调用。新事件从 `PartyManager::StartProcessingStateChanges()` 作为零个或多个 `PartyStateChange` 结构的数组报告。一旦游戏处理完 *状态变更*,便使用 `PartyManager::FinishProcessingStateChanges()` 返回该数组。

`PartyStateChange` 结构本身不是一个完整的对象。它是一个基础头部,将被强制转换为一个更详细的结构,其中包含关于特定完成或通知类型的信息、相关对象的指针以及任何错误信息。

后续主题将详细描述如何处理 *状态变更*。

## 后续步骤

* [了解 PlayFab Party 邀请和安全模型](/services/playfab/multiplayer/networking/concepts-invitations-security-model)
* [了解 PlayFab Party 如何与你的发现流程交互](/services/playfab/multiplayer/networking/concepts-discovery)
* [详细了解 PlayFab Party 聊天通信](/services/playfab/community/voice-communications/concepts-chat)
* 了解如何处理 PlayFab Party 中的异步操作和通知


## Related topics

- [使用多个 PlayFab Party 网络](/zh-CN/services/playfab/multiplayer/networking/concepts-multiple-networks.md)
- [使用多人 SDK 将 Party 与 Lobby 集成](/zh-CN/services/playfab/multiplayer/networking/party-lobby-integration.md)
- [PlayFab Party 功能](/zh-CN/services/playfab/multiplayer/networking/party-features.md)
- [PFProfilesEntityDataObject](/zh-CN/services/playfab/api-references/c/pfprofilestypes/structs/pfprofilesentitydataobject.md)
- [XblMultiplayerGetSessionAsync](/zh-CN/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayergetsessionasync.md)
