快速入門指南:將 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 OSSLocalUser建構 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);
}
}
}
