次の方法で共有


クイック スタート ガイド: PlayFab オンライン サブシステムと PlayFab Unreal Engine Marketplace プラグインの統合

このクイック スタート ガイドは、既存の PlayFab Online Subsystem (OSS) 統合プロジェクトに PlayFab SDK Unreal Engine (UE) Marketplace プラグインを統合する際に役立ちます。

PlayFab SDK プラグインは、PlayFab の管理操作、クライアント操作、サーバー操作 (プレイヤー認証、仮想アイテムと仮想通貨の管理、ソーシャル機能の作成など) を実行するために使用されます。 PlayFab Online サブシステムと組み合わせて使用することにより、Unreal Engine プロジェクト用の広範な PlayFab 機能全般にプロジェクトからアクセスできます。

PlayFab OSS または PlayFab SDK プラグインを相互に依存しない形で使用する場合、最初の手順はユーザーの認証です。 適切なセットアップをせずに両方を同じプロジェクト内で使用すると、PlayFab OSS と PlayFab SDK プラグインの両方で、同じユーザーに対して別々に認証呼び出しが実行されます。

このクイック スタート ガイドに従えば、PlayFab OSS で認証を実行し、その認証を PlayFab SDK プラグインで再利用することにより、シームレスなユーザー認証エクスペリエンスを実現できます。

前提条件

  • PlayFab OSS がプラグインとして <game>.build.cs ファイルに統合されている必要があります。 次の例では、統合を許可するトグル オプションを作成し、#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");
    }
    
  • PlayFab SDK プラグインが <game>.build.cs ファイルに統合されている必要があります。 次の例では、統合を許可するトグル オプションを作成し、#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 に新設された、PlayFab OSS ユーザー認証フローの完了時にトリガーを発生させるパブリック AuthenticateUserComplete デリゲートを利用するために、 このデリゲートをバインドして 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;
    

手順

完全なコード例に進むこともできます。

  1. 正しいヘッダーをインクルードする

    #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
    
  2. PlayFab OSS を取得する

    FOnlineSubsystemPlayFab* PFOnlineSub = static_cast<FOnlineSubsystemPlayFab*>(IOnlineSubsystem::Get(TEXT("PLAYFAB")));
    
  3. AuthenticateUserComplete デリゲートにバインドする

    const FOnlineIdentityPlayFabPtr PlayFabIdentityInterface = PFOnlineSub->GetIdentityInterfacePlayFab();
    PlayFabIdentityInterface->AddOnAuthenticateUserCompleteDelegate_Handle
    (
        0, // LocalUserNum
        FOnAuthenticateUserCompleteDelegate::CreateUObject(this, &UGameInstance::OnAuthenticateUserComplete)
    );
    

    このデリゲートにバインドする関数は、デリゲートと同じシグネチャを持っている必要があります。 次に例を示します。

    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
        });
    )
    
  4. 認証結果を処理する: デリゲートにバインドした関数で、認証の結果を処理します。 認証が成功した場合は、デリゲート トリガーからの platformUserIdStr を介して、認証されたローカル ユーザーを取得します。 次に、PlayFab OSS LocalUser から PlayFab LoginResult を構築します。

    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);
            }
        }
    }
    
  5. 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);
        }
    }
}