Xbox 要求

如果游戏面向 Xbox 主机,必须遵守一组要求,以确保在与 Xbox Live 交互时具有一致的功能和行为。 这组要求列在 Xbox 要求(简称 XR)中。 XR 与在电脑和其他平台上使用游戏中 Xbox Live 所需的策略交互和重叠。 在这里,将介绍 PlayFab 群的最佳做法,这些做法将帮助你遵守这些要求。

如需快速参考,请参阅下表,将 PlayFab 群方案与其解决的 XR 相匹配:

方案 XR
将 PlayFab 群与 Xbox Live 用户的聊天设置和特权保持一致 XR-015XR-045
维护多人游戏会话状态文件 XR-067
标识跨网络游戏会话玩家 XR-007
尊重 Xbox Live 用户的跨网络通信权限 XR-007
不允许跨平台玩游戏时,使用 PlayFab 群邀请限制对网络的访问 XR-007
与 Xbox Live 档案设置保持同步 XR-048
支持平台多人游戏加入流程 XR-064XR-124
好友列表 XR-007XR-070
遵守 Xbox Live 服务重试策略和服务访问限制 XR-074XR-132

PlayFab Party Xbox Live 帮助程序库

除核心 PlayFab 群库之外,我们还提供了一个 Xbox Live 帮助程序库,旨在帮助遵守 Xbox Live 策略以及扩展 XR。 不需要使用此帮助程序库,但强烈建议使用此帮助程序库,并将其视为最佳做法。 此处提供的示例将假定使用 Xbox Live 帮助程序库。

将 PlayFab 群与 Xbox Live 用户的聊天设置和特权保持一致

PlayFab Party 使用聊天通信的选择加入模型,并且默认情况下将两个聊天控件之间的所有通信限制为两个参与者都启用的通信集。 如需了解详情,请参阅有关聊天权限和静音文档。

PlayFab 群的 Xbox Live 帮助程序库指示应启用哪组聊天权限以匹配当前在群会话中进行通信的 Xbox Live 用户首选项和权限。 有关详细信息,请参阅有关尊重 Xbox Live 用户的隐私设置和权限的文档。

通过正确使用 PlayFab 群和 Xbox Live 帮助程序库,游戏可以完全满足 XR-015 指定的要求,并满足 XR-045指定的相关通信要求。 有关 PlayFab Party 范围之外的进一步要求,请参阅 XR-045 技术文档。

维护多人游戏会话状态文件

PlayFab 群不提供任何类型的 Xbox 用户名单。 它依赖于使用多人游戏会话目录服务 (MPSD) 的游戏来维护名单并将群网络活动与游戏会话中的用户相关联。 PlayFab 群将在远程终结点聊天控件进出群网络时进行广播发。 与这些对象关联的 PlayFab 实体 ID 应与 MPSD 文档中的 Xbox 用户匹配,以识别哪些 PlayFab 群对象代表游戏会话中的 Xbox 用户。 对于跨平台游戏场景,未与 Xbox 用户关联的 PlayFab 实体可能代表另一个多人游戏生态系统中的用户。

如果要识别 Xbox 用户,应在 PlayFab 实体 ID 与 Xbox Live 用户之间生成映射。 为此,建议将会话的 Xbox Live 用户列表存储在 MPSD 文档中,并使用 Xbox Live 帮助程序库将这些 Xbox Live 用户转换为 PlayFab 实体 ID。 有关示例,请参阅Xbox Live 用户 ID 和 PlayFab 实体 ID 之间的映射

除了提供群网络名单外,MPSD 文档还推动 Xbox 多人游戏生态系统中的许多多人游戏体验,例如匹配、平台邀请、最近的玩家列表和正在进行的加入。 有关如何将群网络合并到这些 MPSD 流的详细信息,请参阅 将 PlayFab 群与 MPSD 结合使用

有关详细信息,请参阅 MPSD 概述

重要

本部分提供将 PlayFab 群与 MPSD 一起使用时的最佳做法,但 PlayFab 群本身并不隐式满足 XR-067 的 MPSD 要求。 有关满足这些要求的信息,请参阅 XR-067 技术文档。

在跨平台游戏群游戏中使用 Xbox 客户端

对于跨平台游戏场景,在与 Xbox Live 生态系统交互时,请记住以下最佳实践。

重要

本部分提供了在 Xbox Live 的跨平台游戏场景中使用 PlayFab 群的最佳实践,但 PlayFab 群的使用并不隐式满足 XR-007 的跨平台游戏要求。 有关满足这些要求的信息,请参阅 XR-007 技术文档。

标识跨网络游戏会话玩家

在多人游戏生态系统中,可识别和却分唯一的玩家。 为此,PlayFab 群在可能与会话中的用户关联的各种对象上提供 PlayFab 实体 ID:PartyLocalUserPartyEndpointPartyChatControl

PlayFab Party API 不提供跨网络显示名称。 在 UI 中显示 Xbox 用户时,应该使用他们的玩家代号,并从 MPSD 文档中的 Xbox 用户 ID 解析玩家代号。 非 Xbox 用户应根据 XR-007 中的指南在 UI 中显示。 如果缺少平台提供的显示名称,PlayFab 通过 GetPlayerProfile 提供显示名称支持。 加入网络时,玩家应将其显示名称发布在共享会话文档中,供其他玩家查看。

尽管 PlayFab 群库将某些对象与 PlayFab 用户相关联(通过 PlayFab 实体 ID),但库不提供识别 PlayFab 用户可能与哪些多人游戏生态系统相关联的功能。 若要将 Xbox Live PlayFab 用户与其他多人游戏生态系统中的用户区分开来,建议使用 MPSD 交叉引用群网络中的 PlayFab 实体 ID。 有关通过 MPSD 区分 Xbox Live 玩家和非 Xbox Live 玩家的更多信息,请参阅维护多人会话文档部分。

有关使用 Xbox Live 识别跨平台游戏网络中用户的要求的更多信息,请参阅 XR-007

尊重 Xbox Live 用户的跨网络通信权限

PlayFab 群不隐式遵守 Xbox Live 的跨网络通信限制。 因此,PlayFab 群 Xbox Live 帮助程序库提供查询 Xbox Live 用户的跨网络通信权限所需的功能。 必须使用此信息来符合 XR-007 中指定的跨网络通信要求。

如果需要了解详情,请参阅尊重跨网络通信

不允许跨平台玩游戏时,使用 PlayFab 群邀请限制对网络的访问。

Xbox Live 用户需要跨网络权限才能在跨网络游戏会话中与非 Xbox Live 用户交互。 PlayFab 群并未隐式遵守这些跨网络限制(在 XR-007 中概述),因此必须在 PlayFab 群库之外查询此权限。 如果未授予这些权限,则应限制群网络仅允许游戏会话的 MPSD 文档中已知的 Xbox Live 用户。 可以通过增强我们的示例 加入流程流 来使用仅允许已知 Xbox 用户加入网络的群邀请来实现此目的。

首先,确保使用受限邀请创建群网络。

PartyString networkCreatorEntityId;
RETURN_VOID_IF_FAILED(m_localPartyUser->GetEntityId(&networkCreatorEntityId));

PartyInvitationConfiguration newNetworkInitialInvite{};
newNetworkInitialInvite.identifier = nullptr; // let Party select the invitation identifier for simplicity
newNetworkInitialInvite.revocability = PartyInvitationRevocability::Anyone; // the initial invitation must be revocable by anyone

// this initial invitation only allows the original xbl user creating the network
newNetworkInitialInvite.entityIdCount = 1;
newNetworkInitialInvite.entityIds = &networkCreatorEntityId;

PartyError error = PartyManager::GetSingleton().CreateNewNetwork(
    m_localPartyUser,
    &networkConfiguration,
    0,
    nullptr,
    &newNetworkInitialInvite,
    nullptr,
    nullptr,
    nullptr);

加入流程流类似,新 Xbox 用户想要加入网络时,他们将首先将自己添加到会话文档中。 当希望自己加入网络的玩家看到更新时,他们将更新邀请集以反映会议文件。 这将确保只有会话文档中的用户(保证是 Xbox Live 用户)才能加入网络。

void
OnSessionDocumentUpdated(
    PartyNetwork* network,
    uint32_t usersInDocumentCount,
    const uint64_t* usersInDocument
    )
{
    PartyInvitationConfiguration newInvite{};
    newInvite.identifier = nullptr; // let Party select the invitation identifier for simplicity
    newInvite.revocability = PartyInvitationRevocability::Creator; // must be revocable by the creator only

    // the updated invite should contain all users currently in the document
    std::vector<PartyString> entityIdsInDocument;
    for (uint32_t i = 0; i < usersInDocumentCount; ++i)
    {
        uint64_t xboxUserId = usersInDocument[i];
        // Call title-defined xuid->entityid mapping helper
        PartyString xboxUserEntityId = GetEntityIdFromXboxUserId(xboxUserId);
        if (xboxUserEntityId != nullptr)
        {
            entityIdsInDocument.push_back(xboxUserEntityId);
        }
        else
        {
            DEBUGLOG("User %llu did not have a matching entity ID.", xboxUserId);
        }
    }
    newInvite.entityIdCount = entityIdsInDocument.size();
    newInvite.entityIds = entityIdsInDocument.data();

    // Create a new invitation which includes all of the users currently in the document
    PartyInvitation* newInvitation;
    PartyError error = network->CreateInvitation(
        m_localUser,
        &newInvite,
        nullptr,
        &newInvitation);
    if (PARTY_FAILED(error))
    {
        DEBUGLOG("PartyNetwork(0x%p)::CreateInvitation failed! (error=0x%x)", network, error);
        return;
    }

    // Post the invitation's id somewhere that it can be seen by anyone trying to join/rejoin
    PostInvitationToMPSD(newInvite);

    // Cleanup previous invitations. This isn't strictly necessary, but is a good practice.
    uint32_t invitationCount;
    PartyInvitationArray invitations;
    error = network->GetInvitations(&invitationCount, &invitations);
    if (PARTY_FAILED(error))
    {
        DEBUGLOG("PartyNetwork(0x%p)::GetInvitations failed! (error=0x%x)", network, error);
        return;
    }

    for (uint32_t i = 0; i < invitationCount; ++i)
    {
        if (invitations[i] == newInvite)
        {
            continue; // don't prune the old invitation
        }

        PartyInvitation* oldInvitation = invitations[i];

        error = network->RevokeInvitation(m_localUser, oldInvitation, nullptr);
        if (PARTY_FAILED(error))
        {
            DEBUGLOG("PartyNetwork(0x%p)::RevokeInvitation failed! (err=0x%x)", network, error);
        }
    }
}

注意

由于需要在 Xbox Live 用户 ID 和 PlayFab 实体 ID 之间进行转换,因此建议在两者之间构建映射。 有关如何执行此操作的示例,请参阅Xbox Live 用户 ID 和 PlayFab 实体 ID 之间的映射

与 Xbox Live 档案设置保持同步

默认情况下,PlayFab 群符合 XR-048 中的档案设置要求。 库不会保留任何 Xbox Live 档案设置的持久缓存。 当使用 PlayFab 群需要档案设置时,将从 Xbox Live 查询设置并在与设置关联的 PlayFab Party API 对象的生命周期内保持有效,但不会在对象的多个实例中持续存在。

有关在 PlayFab 群之外使用 Xbox Live 档案设置数据的信息,请参阅 XR-048 技术文档。

支持平台多人游戏加入流程

在 Xbox 上,玩家可以通过加入流程和平台邀请功能加入多人游戏。 PlayFab 群不直接与这些平台功能集成,但支持通过 PartyNetworkDescriptorPartyInvitation 对象进行使用。 PartyNetworkDescriptor 对象提供远程用户查找和连接到群网络所需的连接信息,并且可以通过 PartyManager::SerializeNetworkDescriptor 进行序列化。 PartyInvitation 对象为远程用户提供用于身份验证和加入群网络的 ID。 如果要使用远程用户通过加入流程和平台邀请加入多人游戏,将序列化网络描述符和群邀请标识符集成到预先存在的流程中。 示例流程也可以在将 PlayFab 群与 MPSD 结合使用文档中找到。

如果需要详细了解平台多人加入流程要求,请参阅 XR-064XR-124 技术文档。

好友列表

即使 PlayFab 群不会与任何平台上的好友列表进行本地交互,但多人游戏可能仍需要考虑针对不同场景的好友列表。 有关与 Xbox Live 和跨网络好友列表交互时的要求和指南信息,请参阅以下文档:

遵守 Xbox Live 服务重试策略和服务访问限制。

PlayFab 群不会直接与 Xbox Live 帮助程序库 之外的 Xbox Live 服务交互。 Xbox Live 帮助程序库在内部符合相关 Xbox Live 服务的重试策略和访问限制,如 XR-074XR-132中所述。 此外,还可以通过 Xbox Live 帮助程序库报告的以下错误代码来识别由于符合这些服务策略而导致的 API 故障:PartyXblChatPermissionMaskReason::XboxLiveServiceErrorPartyXblStateChangeResult::PartyServiceError

有关在 Xbox Live 帮助程库之外遵守这些服务政策的更多信息,请参阅 XR-074XR-132 技术文档。