主关联标识
任何跨平台进度策略的首要要求是确定哪个玩家标识将跨越各个游戏平台。玩家需要能够在提供该游戏的任何设备上使用此标识登录。对于第一方游戏,这通常是 Microsoft 帐户 (MSA)/XBOX 帐户。对于许多第三方而言,这可能是通过 OpenID Connect 实现公开的发行商标识。此玩家标识需要满足以下两个要求:- 在玩家可能玩该游戏的每个平台上均可供玩家使用
- 受现有 PlayFab Login 调用支持,例如
LoginWithXbox或LoginWithOpenIdConnect
平台原生标识
平台原生标识是玩家运行游戏所在平台提供的帐户系统。示例包括:- Steam:Steam 帐户和身份验证票证 (
ISteamUser::GetAuthTicketForWebApi) - PC/主机上的 XBOX:MSA/XBOX
XUserHandle和 XSTS 令牌 - PlayStation:PSN 在线 ID/帐户
- Nintendo:Nintendo 服务帐户/设备 ID
PFLocalUserHandle(例如 PFLocalUserCreateHandleWithSteamUser 或包装 XUserHandle)。在适当情况下,它们也可用于通过特定于提供程序的 PlayFab Login API(例如 LoginWithSteam、LoginWithXbox)进行身份验证。
在跨平台进度方案中,平台原生标识会关联到主关联标识,以便进度和权利随玩家跨平台流转。本文档中推荐的工作流使用平台原生标识作为本地用户上下文,并使用主关联标识作为跨平台锚点。
关联策略选项
本文档探讨两种相关策略:- 所有玩家在游戏之前必须将其平台原生标识与你的主关联标识进行关联。
- 平台原生标识与主关联标识之间的关联是可选的,但强烈建议在游戏之前进行关联。
期望状态
无论采用哪种策略,最终目标都是让每个玩家进入相同的状态。其主关联标识应与其游戏所用每台设备上的平台原生标识相关联。在该状态下,进度始终绑定到主关联标识,并且平台原生标识也可以在所有平台上用作主标识的有效代理标识。 在某些平台上,主关联标识就是平台原生标识(在 XBOX 上运行的第一方游戏)。在这些情况下,达到期望状态变得非常简单。本文档不深入探讨这些情况,因为现有的登录和关联指南已经足够。LocalUser 与登录
区分 PlayFab SDK 中存在的两个相关但独立的概念非常重要。 LocalUserCreate 调用会构造本地用户对象并返回 PFLocalUserHandle,而不执行任何身份验证。它通过特定于平台的或持久化的本地 ID(例如包装 XUserHandle)来标识和缓存用户,以便你可以在各个操作和游戏实例之间重用相同的本地上下文。此操作完全是本地的:它不会发出网络请求、获取实体令牌或创建 PlayFab 帐户。 相比之下,Login 调用会使用 PlayFab 对本地用户进行身份验证,并建立经过身份验证的实体,包括令牌和 ID。Login 调用会执行网络请求(例如 /Client/LoginWithXbox)并遵循 createAccount 等标志;成功后,结果会被缓存,以便后续调用可以重用经过身份验证的状态。 简而言之,创建本地用户会设置 PlayFab Game Saves 所需的本地标识和句柄管理,而登录则是联系 PlayFab 进行身份验证并启用需要实体的 API 的步骤。策略 1 - 必需的主标识关联
为了说明此策略,我们将讨论一款在 Steam 上发布的 XBOX 第一方游戏。该游戏使用 XBOX/MSA 作为其主关联标识。它要求所有玩家在进行任何游戏之前登录其 XBOX/MSA。它仍使用基于 Steam 标识的 LocalUserHandle,但会阻止实际登录,直到玩家创建并关联 XBOX 标识。在后续启动时,由于已验证关联,它可以直接使用 Steam 标识继续。概要
- 玩家必须先使用跨平台标识 (XBOX/MSA) 登录,然后才能游戏。
- 从平台帐户 (Steam) 创建本地玩家,但在 XBOX/MSA 登录完成之前暂停在线游戏。
- XBOX/MSA 登录后,将平台帐户关联到跨平台帐户。
- 刷新本地平台配置文件,使其连接到跨平台帐户。
- 以后的启动将无缝进行:由于关联已建立,玩家可以直接开始游戏。
详细演练
创建 Steam 本地用户句柄- 调用
PFLocalUserCreateHandleWithSteamUser(serviceConfigHandle, customContext, outLocalUserHandle)。 - 结果:
PFLocalUserHandle;尚未进行身份验证。
- 调用
PFLocalUserLoginAsync(localUserHandle, /*createAccount*/ false, async)。 - 完成时,如果
PFLocalUserLoginGetResult失败并返回E_PF_ACCOUNT_NOT_FOUND,则触发 XBOX 登录以引导创建帐户。 - 如果
PFLocalUserLoginGetResult成功,则说明我们已有处于期望状态的帐户并且已联机。工作流完成。
如果你的游戏要求跨平台标识保持与当前用户关联(例如,游戏要求 XBOX 登录,并期望实体的 XBOX 关联与当前登录的 XBOX 帐户匹配),则仅平台登录成功是不够的。登录后调用
PFAccountManagementClientGetAccountInfoAsync,以验证跨平台关联是否与当前用户匹配。如果不匹配,则实体可能绑定到过时的跨平台标识,请按照下面的通过 XBOX 登录和关联 Steam 步骤进行重新对齐。- 构建
PFAuthenticationLoginWithXUserRequest:- 设置
createAccount=true,以便在需要时创建 PlayFab 帐户。 - 提供 PC 上已登录 XBOX 用户的
XUserHandle。
- 设置
- 调用
PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, request, async)。 - 使用
PFAuthenticationLoginWithXUserGetResultSize(...)和PFAuthenticationLoginWithXUserGetResult(...)完成操作以获取PFEntityHandle。 - 注意:如果 LoginWithXUser 变体不可用,请使用
PFAuthenticationLoginWithXbox。这需要你自行从XUserHandle中提取 XSTS 令牌。
- 使用当前 Steam 身份验证票证(来自
ISteamUser::GetAuthTicketForWebApi或集成中的等效函数;请在代码中确认确切的函数名称)构建客户端关联请求。 - 调用
PFAccountManagementClientLinkSteamAccountAsync(entityHandle, linkRequest, async)。 - 注意:“LinkSteamAccount” 位于 Account Management 下,而不是 Authentication 下。
- 成功后,玩家的 Steam 标识将关联到 XBOX 支持的 PlayFab 帐户。
- 再次调用
PFLocalUserLoginAsync(steamLocalUserHandle, /*createAccount*/ false, async)。 PFLocalUserLoginGetResult现在会成功;生成的PFEntityHandle绑定到 Steam 本地用户。
- Game Save 和其他在线 API 使用经过身份验证的
PFEntityHandle。 - 由于所有关联均已就绪,后续启动游戏时可以直接开始游戏。
PFLocalUserCreateHandleWithSteamUser本身不会登录,但尝试调用PFGameSaveFilesAddUserWithUiAsync会导致登录尝试。请确保在该调用之前已完成帐户关联流程。
关联冲突处理
将 Steam 关联到 XBOX 支持的实体时,可能出现两种不同的冲突。每种冲突需要不同的补救措施:
推荐流程:
- XBOX 登录后,调用
PFAccountManagementClientGetAccountInfoAsync(xboxEntity, getInfoRequest, async)以获取帐户信息并检查已关联的标识。 - 如果实体已关联了另一个 Steam 帐户:
- 警告玩家继续操作会从此实体中删除旧的 Steam 关联。征得同意。
- 调用
PFAccountManagementClientUnlinkSteamAccountAsync(xboxEntity, unlinkRequest, async)删除现有的 Steam 关联。 - 然后使用当前 Steam 票证调用
PFAccountManagementClientLinkSteamAccountAsync。
- 如果关联调用返回
E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED(该 Steam 帐户属于另一个实体):- 警告玩家此 Steam 帐户已与另一个 PlayFab 帐户关联,在此处关联会删除该关联。
- 征得同意后使用
forceLink=true重试。
示例 C++ 流程(Steam 优先门控、XBOX 引导、关联 Steam、再次使用 Steam 登录):
此示例使用
static XAsyncBlock 变量来简化生存期管理。生产代码应动态分配异步块(例如作为上下文结构的一部分),以支持并发调用或重入调用。- 使用
E_PF_ACCOUNT_NOT_FOUND来决定是否走 XBOX 引导路径;单独处理其他错误。 - 继续使用 Steam
PFLocalUserHandle;特定于提供程序的 XBOX 登录返回的entityHandle仅用于关联 Steam。 - 关联后,再次使用 Steam 登录,以将实体绑定到 LocalUser。
- 确保获取新的 Steam 票证用于关联。
- 不再需要时关闭句柄(
PFLocalUserCloseHandle、PFEntityCloseHandle)。
策略 2 - 可选的主标识关联
在此方案中,游戏在 Steam 上运行,并使用 XBOX/MSA 作为主关联标识。玩家无需立即登录 XBOX/MSA 即可开始游戏。游戏通过明确的好处说明和警告来鼓励尽早关联,但不会阻止初始游戏。概要
- 使用平台帐户 (Steam) 创建本地玩家,并尝试在不创建新帐户的情况下进行在线游戏。
- 如果在线可用,则继续;如果不可用,则提供以下选择:
- 使用跨平台标识 (XBOX/MSA) 登录以创建统一帐户,或者
- 立即创建仅限平台的帐户并马上开始游戏。
- 通过说明好处和风险,鼓励尽早关联到 XBOX/MSA。
- 当玩家选择关联时:
- 如果直接关联成功,则使用统一帐户继续游戏。
- 如果 XBOX/MSA 帐户在其他地方已有进度,则暂停并询问要保留哪个进度(协调):
- 保留 XBOX/MSA 进度并附加当前平台帐户。
- 保留当前平台进度并推迟关联。
- 关联后,刷新本地平台配置文件,使其连接到统一帐户。
- 以后的启动将无缝进行:玩家可以直接开始游戏(假设未推迟关联)。
详细演练
创建 Steam 本地用户句柄- 调用
PFLocalUserCreateHandleWithSteamUser(serviceConfigHandle, customContext, outLocalUserHandle)。 - 结果:
PFLocalUserHandle;尚未进行身份验证。
- 调用
PFLocalUserLoginAsync(localUserHandle, /*createAccount*/ false, async)。 - 完成时:
- 如果
PFLocalUserLoginGetResult成功,则使用生成的PFEntityHandle并继续联机。- 检查 Steam 支持的帐户是否已关联到 XBOX/MSA。调用
PFAccountManagementClientGetAccountInfoAsync(entityHandle, getInfoRequest, async)并检查已关联的标识。如果未关联,则提示玩家使用下面的流程关联 XBOX(非阻塞),以便将来的跨平台进度能够无缝工作。
- 检查 Steam 支持的帐户是否已关联到 XBOX/MSA。调用
- 如果
PFLocalUserLoginGetResult失败并返回E_PF_ACCOUNT_NOT_FOUND,则玩家将保持离线状态,直到创建帐户。提供两个选择:- 立即创建 XBOX 支持的 PlayFab 帐户:使用 XBOX/MSA 登录(例如
PFAuthenticationLoginWithXUserAsync)。 - 立即使用 Steam 登录并开始游戏:调用
PFLocalUserLoginAsync(localUserHandle, /*createAccount*/ true, async)创建绑定到本地句柄的 Steam 支持的 PlayFab 帐户;成功后,使用生成的PFEntityHandle立即联机。
- 立即创建 XBOX 支持的 PlayFab 帐户:使用 XBOX/MSA 登录(例如
- 对于其他错误,请妥善处理(重试/退避)。
- 如果
- 展示关联的好处(跨平台进度、权利可移植性)。
- 提供 XBOX/MSA 登录。
- 如果玩家稍后发起 XBOX 关联(他们已从当前会话获得 Steam 支持的
PFEntityHandle):- 不要创建新的 XBOX 支持的帐户。
- 通过调用相应的关联 API(例如
PFAccountManagementClientLinkXboxAccountAsync(currentSteamEntity, linkRequest, async)),尝试将 XBOX 标识直接关联到当前 Steam 支持的帐户。 - 如果关联成功,则 XBOX/MSA 标识现已关联;继续正常操作。
- 如果关联因预先存在的关联/冲突错误而失败(XBOX 标识已在其他位置关联),则进入帐户协调模式。立即使用
createAccount=false执行 XBOX/MSA 登录(例如PFAuthenticationLoginWithXUserAsync)以获取 XBOX 支持的PFEntityHandle,然后在提示玩家之前获取配置文件元数据作为上下文。征得同意后,继续进行关联决策。
- 如果玩家没有 XBOX 的现有帐户(引导路径):
- 首先使用
PFAuthenticationLoginWithXUserAsync(或在LoginWithXUser不可用时使用PFAuthenticationLoginWithXboxAsync)以createAccount=false尝试 XBOX/MSA 登录。- 如果登录成功:XBOX/MSA 帐户已有 PlayFab 帐户,并且可能已有进度。进入帐户协调模式以选择要保留的进度。
- 如果登录失败并返回
E_PF_ACCOUNT_NOT_FOUND:通过使用createAccount=true再次登录来创建 PlayFab 帐户。
- 使用
PFAuthenticationLoginWithXUserGetResultSize(...)和PFAuthenticationLoginWithXUserGetResult(...)完成操作以获取PFEntityHandle。
- 首先使用
- 适用于刚刚创建全新 XBOX 支持的 PlayFab 帐户(没有现有 Steam 关联)的情况。
- 如果之前已进入帐户协调,则关联决策和任何所需的
forceLink操作都在那里处理;跳过此步骤。 - 使用当前 Steam 身份验证票证(来自
ISteamUser::GetAuthTicketForWebApi或你的集成)构建客户端关联请求。 - 使用
forceLink=false(默认值)调用PFAccountManagementClientLinkSteamAccountAsync(entityHandle, linkRequest, async)。对于全新帐户,此操作预计会成功。 - 如果关联失败,请将其视为错误情况(意外冲突或身份验证失败)。向玩家显示错误,并考虑在重试之前提示他们重新登录。
- 成功后,玩家的 Steam 标识将关联到 XBOX 支持的 PlayFab 帐户。
- 再次调用
PFLocalUserLoginAsync(steamLocalUserHandle, /*createAccount*/ false, async)。 PFLocalUserLoginGetResult现在会成功;生成的PFEntityHandle绑定到 Steam 本地用户。
- Game Save 和其他在线 API 使用经过身份验证的
PFEntityHandle。 - 由于所有关联均已就绪,后续启动游戏时将能够直接开始游戏。
- 不要使用 XBOX/MSA 登录阻止初始游戏;应尽早提示,但允许玩家推迟。
PFLocalUserCreateHandleWithSteamUser本身不会登录。请确保在调用会触发登录的 API(如PFGameSaveFilesAddUserWithUiAsync)之前完成关联流程。
帐户协调(XBOX/MSA 上已有进度)
当玩家使用已有进度(例如来自主机或其他平台)的 XBOX/MSA 帐户登录时,必须避免盲目创建新帐户或覆盖现有关联。请使用谨慎的两阶段方法进行检测和协调。检测阶段
- 可以通过两种途径进入协调:
- 检测到现有 XBOX/MSA 帐户:使用
createAccount=false尝试 XBOX/MSA 登录。- 如果登录成功,则 XBOX/MSA 标识已有 PlayFab 帐户,并且可能已有进度,此时进入协调。
- 如果登录失败并返回
E_PF_ACCOUNT_NOT_FOUND,则继续进行引导 (createAccount=true)。无需进入协调。
- 检测到延迟关联冲突:将 XBOX/MSA 关联到当前 Steam 支持的帐户时,关联因预先存在的关联/冲突错误而失败(XBOX 标识已与另一个 Steam 标识关联)。
- 立即使用
createAccount=false执行 XBOX/MSA 登录(例如PFAuthenticationLoginWithXUserAsync)以获取 XBOX 支持的PFEntityHandle。 - 获取配置文件元数据(例如最近的进度、存档槽、时间戳)以展示上下文。
- 进入协调以决定要保留哪个进度。
- 立即使用
- 检测到现有 XBOX/MSA 帐户:使用
协调阶段
- 推荐最直接的选项:保留 XBOX/MSA(主关联标识)进度并放弃本地 Steam 进度。这样可以保留跨平台锚点,并避免复杂的合并。
- 玩家实际上有三种选择(游戏可以选择仅提供其中 1-2 种):
- 保留 XBOX/MSA 进度(推荐):继续将当前 Steam 帐户关联到现有的 XBOX 支持的 PlayFab 帐户。
- 保留当前 Steam 进度并取消关联:暂时继续使用 Steam 支持的帐户;不关联或覆盖 XBOX/MSA 数据。下次再次提供关联。
- 保留当前 Steam 进度并放弃 XBOX 进度:切换到 Steam 支持的帐户,并有意放弃 XBOX/MSA 进度。此途径需要明确的游戏设计考量,不应轻易尝试,尤其是当其他平台原生标识已附加到 XBOX 帐户时。本文档不涉及此方案的实现细节。
- 提交之前:
- 为 XBOX 实体调用
PFAccountManagementClientGetAccountInfoAsync,以检查现有的提供程序关联并验证是否已存在 Steam 关联。 - 如果该实体已关联另一个 Steam 帐户,请警告玩家,在添加新关联之前,会从该实体中删除此现有 Steam 关联。这需要在关联当前 Steam 帐户之前调用
PFAccountManagementClientUnlinkSteamAccountAsync。forceLink无法解决此情况。 - 如果当前 Steam 帐户已关联到另一个实体,则调用
PFAccountManagementClientLinkSteamAccountAsync会返回E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED。警告关联会将 Steam 标识从另一个实体移走,然后在征得同意后使用forceLink=true重试。
- 为 XBOX 实体调用
提交操作(基于玩家选择)
- 玩家选择 XBOX/MSA 进度:
- 确保已获取 XBOX 登录实体(如果在检测期间尚未执行,则使用
createAccount=false执行PFAuthenticationLoginWithXUserAsync)。 - 如果 XBOX 实体已关联另一个 Steam 帐户,请先调用
PFAccountManagementClientUnlinkSteamAccountAsync将其删除。 - 将当前 Steam 关联到 XBOX 支持的帐户。如果调用返回
E_PF_LINKED_ACCOUNT_ALREADY_CLAIMED(Steam 位于另一个实体上),请在征得同意后使用forceLink=true重试。 - 再次使用 Steam 本地用户登录 (
PFLocalUserLoginAsync(..., /*createAccount*/ false, ...)) 以绑定实体。
- 确保已获取 XBOX 登录实体(如果在检测期间尚未执行,则使用
- 玩家选择 Steam 进度:
- 如果 Steam 尚无 PlayFab 帐户,则通过
PFLocalUserLoginAsync(..., /*createAccount*/ true, ...)创建/绑定。 - 推迟 XBOX 关联;允许立即开始游戏。下次再次提供关联。
- 如果 Steam 尚无 PlayFab 帐户,则通过
注意
- 始终获取并显示足够的上下文,以便玩家做出决定。
- 记录协调结果的遥测数据,以便随着时间推移改进提示和默认设置。
