快速入门指南:将 PlayFab Online Subsystem 与 PlayFab Unreal Engine Marketplace 插件集成
本快速入门指南帮助你将 PlayFab SDK Unreal Engine (UE) Marketplace 插件集成到你现有的 PlayFab Online Subsystem (OSS) 集成项目中。 PlayFab SDK 插件用于执行 PlayFab 管理、客户端和服务器操作,例如玩家身份验证、虚拟物品和货币管理以及社交功能创建。与 PlayFab Online Subsystem 一起使用时,你的项目可以访问适用于 Unreal Engine 项目的全部 PlayFab 功能。 单独使用 PlayFab OSS 或 PlayFab SDK 插件时,第一步是对用户进行身份验证。在同一项目中同时使用这两者但未进行适当设置时,PlayFab OSS 和 PlayFab SDK 插件会对同一用户分别发起单独的身份验证调用。 本快速入门指南帮助你通过 PlayFab OSS 进行身份验证,并将该身份验证重用于 PlayFab SDK 插件,从而实现无缝的用户身份验证体验。先决条件
-
确保你在
<game>.build.cs文件中将 PlayFab OSS 集成为插件。在下面的示例中,我们创建了一个开关选项以允许集成,并设置了一个用于#ifdef保护的定义。// PlayFab OnlineSubsystem Plugin Settings. // // While the PlayFab OSS is integrated with the game at an engine level, we cannot directly access // PF OSS headers unless we integrate it as a plugin. // // `bOSSPlayFabAsPlugin` must be set to true to expose the PlayFab OSS headers directly to the game. bool bOSSPlayFabAsPlugin = false; if (bOSSPlayFabAsPlugin) { PublicDependencyModuleNames.AddRange(new string[] { "OnlineSubsystemPlayFab" }); PublicDefinitions.Add("WITH_OSS_PLAYFAB=1"); } -
确保你在
<game>.build.cs文件中集成了 PlayFab SDK 插件。在下面的示例中,我们创建了一个开关选项以允许集成,并设置了一个用于#ifdef保护的定义。// PlayFab SDK Plugin Settings. // // `bPlayFabPlugin` must be set to true to enable compilation and integration with the PlayFab // SDK Plugin. // Ensure that the PF SDK Plugin is installed via Engine plugin or as a local game plugin. bool bPlayFabPlugin = false; if (bPlayFabPlugin) { PrivateDependencyModuleNames.AddRange(new string[] { "PlayFab", "PlayFabCpp", "PlayFabCommon" }); PublicDefinitions.Add("WITH_PLAYFAB_PLUGIN=1"); } -
在更新
<game.build.cs>文件后(以及每次后续更新时),请务必通过右键单击.uproject文件并选择Generate Visual Studio Project Files来重新生成游戏的 Visual Studio 项目文件。 -
PlayFab OSS 现在提供一个公共
AuthenticateUserComplete委托,该委托在 PlayFab OSS 用户身份验证流程完成时触发。绑定到此委托以检索你的 PlayFab OSS 身份验证的详细信息。/** * Delegate used on the completion of FOnlineIdentityPlayFab::AuthenticateUser(). * * @param LocalUserNum the controller number of the associated user that made the request * @param bWasSuccessful true if authentication was successful, false if there was an error * @param PlatformUserIdStr user identifier returned from the service. * @param ErrorStr string representing the error condition */ DECLARE_MULTICAST_DELEGATE_FourParams(FOnAuthenticateUserComplete, int32 /*LocalUserNum*/, bool /*bWasSuccessful*/, const FString& /*PlatformUserIdStr*/, const FString& /*ErrorStr*/); typedef FOnAuthenticateUserComplete::FDelegate FOnAuthenticateUserCompleteDelegate;
步骤
你也可以跳转到完整代码示例。-
包含正确的头文件
#ifdef WITH_OSS_PLAYFAB #include "OnlineSubsystemPlayFab.h" #endif // WITH_OSS_PLAYFAB #ifdef WITH_PLAYFAB_PLUGIN #include "PlayFab.h" #include "PlayFabCommon.h" #include "Core/PlayFabClientDataModels.h" #endif // WITH_PLAYFAB_PLUGIN -
检索 PlayFab OSS
FOnlineSubsystemPlayFab* PFOnlineSub = static_cast<FOnlineSubsystemPlayFab*>(IOnlineSubsystem::Get(TEXT("PLAYFAB"))); -
绑定到
AuthenticateUserComplete委托绑定到此委托的函数必须具有与委托相同的签名。例如:const FOnlineIdentityPlayFabPtr PlayFabIdentityInterface = PFOnlineSub->GetIdentityInterfacePlayFab(); PlayFabIdentityInterface->AddOnAuthenticateUserCompleteDelegate_Handle ( 0, // LocalUserNum FOnAuthenticateUserCompleteDelegate::CreateUObject(this, &UGameInstance::OnAuthenticateUserComplete) );你也可以将一个 lambda 绑定到委托。例如:void UGameInstance::OnAuthenticateUserComplete(int32 localUserNum, bool bWasSuccessful, const FString& platformUserIdStr, const FString& error)// We don't pass the `FOnlineIdentityPlayFabPtr` pointer through the lambda capture since the original // local isn't guaranteed to live longer than the lambda and we want to avoid dangling references. // // You can retrieve `FOnlineIdentityPlayFabPtr` again inside the lambda. PlayFabIdentityInterface->AddOnAuthenticateUserCompleteDelegate_Handle ( 0, // LocalUserNum FOnAuthenticateUserCompleteDelegate::CreateLambda([this](int32 localUserNum, bool bWasSuccessful, const FString& platformUserIdStr, const FString& error) { // lambda execution }); ) -
处理身份验证结果:在绑定到该委托的函数中,处理身份验证的结果。如果身份验证成功,则通过委托触发时提供的
platformUserIdStr检索已通过身份验证的本地用户。然后,从 PlayFab OSS 的LocalUser构造一个 PlayFabLoginResult。void UGameInstance::OnAuthenticateUserComplete(int32 localUserNum, bool bWasSuccessful, const FString& platformUserIdStr, const FString& error) { if (!bWasSuccessful) { UE_LOG(LogOnlineGame, Error, TEXT("OSS PlayFab AuthenticateLocalUser Failed. Error: %s"), *error); return; } UE_LOG(LogOnlineGame, Display, TEXT("[%s] AuthenticateLocalUser Complete"), ANSI_TO_TCHAR(__FUNCTION__)); FOnlineSubsystemPlayFab* PFOnlineSub = static_cast<FOnlineSubsystemPlayFab*>(IOnlineSubsystem::Get(TEXT("PLAYFAB"))); const FOnlineIdentityPlayFabPtr PlayFabIdentityInterface = PFOnlineSub->GetIdentityInterfacePlayFab(); if (PlayFabIdentityInterface) { if (const auto LocalUser = PlayFabIdentityInterface->GetPartyLocalUserFromPlatformIdString(platformUserIdStr)) { // Setting PlayFab SDK Settings for future API calls auto& PFCommonModule = IPlayFabCommonModuleInterface::Get(); PFCommonModule.SetClientSessionTicket(LocalUser->GetSessionTicket()); PFCommonModule.SetEntityToken(LocalUser->GetEntityToken()); // Create EntityKey auto LocalEntityKey = MakeShared<PlayFab::ClientModels::FEntityKey>(); LocalEntityKey->Id = LocalUser->GetEntityId(); LocalEntityKey->Type = LocalUser->GetEntityType(); // Create EntityToken auto LocalEntityToken = MakeShared<PlayFab::ClientModels::FEntityTokenResponse>(); LocalEntityToken->Entity = LocalEntityKey; LocalEntityToken->EntityToken = LocalUser->GetEntityToken(); // Create LoginResult PlayFab::ClientModels::FLoginResult LoginResult; LoginResult.EntityToken = LocalEntityToken; LoginResult.LastLoginTime = LocalUser->GetEntityTokenUpdateTime(); LoginResult.PlayFabId = LocalUser->GetPlayFabId(); LoginResult.SessionTicket = LocalUser->GetSessionTicket(); // With `LoginResult` populated, we can now use the PlayFab SDK Plugin APIs // however we wish. This state is considered "authenticated". // // This delegate signature functions does not return anything. You can pass `LoginResult` // out of this function however you wish. // // Example psuedocode for a non-existent function that takes `LoginResult` as a parameter: // void UGameInstance::OnAPILoginSuccess(PlayFab::ClientModels::FLoginResult LoginResult); } } } -
使用 PlayFab SDK 插件 API:在
LoginResult填充完成后,你现在可以随意使用 PlayFab SDK 插件 API。此状态被视为“已通过身份验证”。
完整代码示例
#ifdef WITH_OSS_PLAYFAB
#include "OnlineSubsystemPlayFab.h"
#endif // WITH_OSS_PLAYFAB
#ifdef WITH_PLAYFAB_PLUGIN
#include "PlayFab.h"
#include "PlayFabCommon.h"
#include "Core/PlayFabClientDataModels.h"
#endif // WITH_PLAYFAB_PLUGIN
...
void UGameInstance::Init()
{
Super::Init();
...
// This is an example scenario of integrating the PlayFab OnlineSubsystem with the
// PlayFab SDK Plugin.
//
// In this scenario, you can authenticate via the PlayFab OSS,
// and then re-use that authentication with the PlayFab SDK Plugin.
//
// PF OSS offers a public `AuthenticateUserComplete` delegate that can be bound;
// this delegate triggers on completion of the PF OSS user authentication flow.
//
// Below is an example of a game binding to that delegate, retrieving the
// authenticated local user via the `platformUserIdStr` from the delegate
// trigger, and then constructing a PlayFab `LoginResult` from the PF OSS
// `LocalUser.`
//
// These definitions are defined in `<game>.build.cs`.
#if defined(WITH_OSS_PLAYFAB) && defined(WITH_PLAYFAB_PLUGIN)
// Explicitly retrieve the PlayFab OSS - we can't assume it's the default OSS.
FOnlineSubsystemPlayFab* PFOnlineSub = static_cast<FOnlineSubsystemPlayFab*>(IOnlineSubsystem::Get(TEXT("PLAYFAB")));
UE_LOG(LogOnlineGame, Warning, TEXT("Retrieved PFOnlineSub"));
if (PFOnlineSub)
{
const FOnlineIdentityPlayFabPtr PlayFabIdentityInterface = PFOnlineSub->GetIdentityInterfacePlayFab();
PlayFabIdentityInterface->AddOnAuthenticateUserCompleteDelegate_Handle
(
0, // LocalUserNum
FOnAuthenticateUserCompleteDelegate::CreateUObject(this, &UGameInstance::OnAuthenticateUserComplete)
);
}
else
{
UE_LOG(LogOnlineGame, Error, TEXT("UGameInstance::Init: Unable to find OnlineSubsystemPlayFab"));
}
#endif // WITH_OSS_PLAYFAB && WITH_PLAYFAB_PLUGIN
...
}
void UGameInstance::OnAuthenticateUserComplete(int32 localUserNum, bool bWasSuccessful, const FString& platformUserIdStr, const FString& error)
{
if (!bWasSuccessful)
{
UE_LOG(LogOnlineGame, Error, TEXT("OSS PlayFab AuthenticateLocalUser Failed. Error: %s"), *error);
return;
}
UE_LOG(LogOnlineGame, Display, TEXT("[%s] AuthenticateLocalUser Complete"), ANSI_TO_TCHAR(__FUNCTION__));
FOnlineSubsystemPlayFab* PFOnlineSub = static_cast<FOnlineSubsystemPlayFab*>(IOnlineSubsystem::Get(TEXT("PLAYFAB")));
const FOnlineIdentityPlayFabPtr PlayFabIdentityInterface = PFOnlineSub->GetIdentityInterfacePlayFab();
if (PlayFabIdentityInterface)
{
if (const auto LocalUser = PlayFabIdentityInterface->GetPartyLocalUserFromPlatformIdString(platformUserIdStr))
{
// Setting PlayFab SDK Settings for future API calls
auto& PFCommonModule = IPlayFabCommonModuleInterface::Get();
PFCommonModule.SetClientSessionTicket(LocalUser->GetSessionTicket());
PFCommonModule.SetEntityToken(LocalUser->GetEntityToken());
// Create EntityKey
auto LocalEntityKey = MakeShared<PlayFab::ClientModels::FEntityKey>();
LocalEntityKey->Id = LocalUser->GetEntityId();
LocalEntityKey->Type = LocalUser->GetEntityType();
// Create EntityToken
auto LocalEntityToken = MakeShared<PlayFab::ClientModels::FEntityTokenResponse>();
LocalEntityToken->Entity = LocalEntityKey;
LocalEntityToken->EntityToken = LocalUser->GetEntityToken();
// Create LoginResult
PlayFab::ClientModels::FLoginResult LoginResult;
LoginResult.EntityToken = LocalEntityToken;
LoginResult.LastLoginTime = LocalUser->GetEntityTokenUpdateTime();
LoginResult.PlayFabId = LocalUser->GetPlayFabId();
LoginResult.SessionTicket = LocalUser->GetSessionTicket();
// With `LoginResult` populated, we can now use the PlayFab SDK Plugin APIs
// however we wish. This state is considered "authenticated".
//
// This delegate signature functions does not return anything. You can pass `LoginResult`
// out of this function however you wish.
//
// Example psuedocode for a non-existent function that takes `LoginResult` as a parameter:
// void UGameInstance::OnAPILoginSuccess(PlayFab::ClientModels::FLoginResult LoginResult);
}
}
}
