メインコンテンツまでスキップ

OSSを使用してアカウントをアップグレードする - ゲーム内登録 - (Unreal Engineモジュール)

Last updated on February 4, 2026

注釈:本資料はAI技術を用いて翻訳されています。

サブシステムの展開

このチュートリアルでは、AGS Online Subsystem (OSS) を使用して、ヘッドレスアカウントを完全なAccelByte Gaming Services (AGS) アカウントにアップグレードする方法を説明します。Byte Warsプロジェクトには、RegisterUserInGameSubsystemという名前のゲームインスタンスサブシステムがすでに作成されています。このサブシステムには、アカウントをアップグレードするための完成した実装が含まれています。ただし、このチュートリアルでは、そのサブシステムのスターターバージョンを使用して、関数をゼロから実装します。

スターターパックの内容

このチュートリアルに従うために、RegisterUserInGameSubsystem_Starterという名前のスターターサブシステムクラスが用意されています。このクラスはリソースセクションで入手でき、以下のファイルで構成されています。

  • ヘッダーファイル: /Source/AccelByteWars/TutorialModules/Access/RegisterUserInGame/RegisterUserInGameSubsystem_Starter.h
  • CPPファイル: /Source/AccelByteWars/TutorialModules/Access/RegisterUserInGame/RegisterUserInGameSubsystem_Starter.cpp

また、/Source/AccelByteWars/TutorialModules/Access/RegisterUserInGame/RegisterUserInGameModels.hファイルにモデルファイルがあります。このファイルには以下のヘルパーが含まれています。

  • バックエンドからのレスポンスを処理するためのデリゲート宣言。

    DECLARE_DELEGATE_ThreeParams(FOnUpgradeAndVerifyAccountComplete, bool bWasSuccessful, const FString& ErrorMessage, const FAccountUserData& NewFullAccount);
    DECLARE_DELEGATE_TwoParams(FOnSendUpgradeAccountVerificationCodeComplete, bool bWasSuccessful, const FString& ErrorMessage);
    DECLARE_DELEGATE_TwoParams(FOnUserInputValidationComplete, bool bIsValid, const FString& ValidationMessage);
  • ログとメッセージを出力するための文字列定数。

    #define SEND_VERIFICATION_CODE_MESSAGE NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Send Verification Code Message", "Sending verification code")
    #define RESEND_VERIFICATION_CODE_MESSAGE NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Send Verification Code Message", "Re-send Verification Code")
    #define UPGRADE_ACCOUNT_MESSAGE NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Message", "Upgrading and verifying account")
    #define EMPTY_REQUIRED_FIELDS_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Empty Required Fields Error", "Required fields cannot be empty")
    #define EMPTY_VERIFICATION_CODE_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Empty Verification Code Error", "Verification code cannot be empty")
    #define EMAIL_INPUT_VIOLATION_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Email Input Violation Error", "E-mail format is invalid")
    #define EMAIL_ALREADY_USED_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Email Already Used Error", "E-mail is already used")
    #define USERNAME_ALREADY_USED_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Username Already Used Error", "Username is already used")
    #define DISPLAYNAME_ALREADY_USED_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Display Name Already Used Error", "Display Name is already used")
    #define PASSWORD_NOT_MATCH_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Password Not Match Error", "Password does not match, retype the password")
    #define UPGRADE_ACCOUNT_UNKNOWN_ERROR NSLOCTEXT(ACCELBYTEWARS_LOCTEXT_NAMESPACE, "Upgrade Account Unknown Error", "Unknown error occurred. Please try again")
    inline const FText GetUpgradeAccountErrorMessage(const EUpgradeAccountErrorTypes ErrorCode)
    {
    switch ((EUpgradeAccountErrorTypes)ErrorCode)
    {
    case EUpgradeAccountErrorTypes::EmailAlreadyUsed:
    return EMAIL_ALREADY_USED_ERROR;
    case EUpgradeAccountErrorTypes::UsernameAlreadyUsed:
    return USERNAME_ALREADY_USED_ERROR;
    case EUpgradeAccountErrorTypes::UniqueDisplayNameAlreadyUsed:
    return DISPLAYNAME_ALREADY_USED_ERROR;
    default:
    return UPGRADE_ACCOUNT_UNKNOWN_ERROR;
    }
    }

認証コードのリクエストを実装する

このセクションでは、メール認証コードのリクエストを送信する関数を実装します。

  1. RegisterUserInGameSubsystem_Starterクラスのヘッダーファイルを開き、以下のヘルパー変数を宣言します。この変数は、同じメールアドレスへの複数の認証コードリクエストを防ぐために、メールアドレスを保存するために使用されます。

    private:
    // ...
    TSet<FString> LastVerificationCodeTargetEmails;
  2. 次に、メール認証コードのリクエストを送信する以下の関数を宣言します。

    public:
    // ...
    void SendUpgradeAccountVerificationCode(
    const FString& EmailAddress,
    const bool bForceResend = false,
    const FOnSendUpgradeAccountVerificationCodeComplete& OnComplete = FOnSendUpgradeAccountVerificationCodeComplete());
  3. 次に、RegisterUserInGameSubsystem_StarterクラスのCPPファイルを開き、上記の関数を定義します。この関数は、ターゲットメールに認証コードを送信するようバックエンドにリクエストを送信します。bForceResendが無効の場合、同じメールアドレスに新しいリクエストを送信しません。

    void URegisterUserInGameSubsystem_Starter::SendUpgradeAccountVerificationCode(
    const FString& EmailAddress,
    const bool bForceResend,
    const FOnSendUpgradeAccountVerificationCodeComplete& OnComplete)
    {
    if (!bForceResend && LastVerificationCodeTargetEmails.Contains(EmailAddress))
    {
    UE_LOG_REGISTERUSERINGAME(Log, TEXT("Verification code already sent to the same e-mail."));
    OnComplete.ExecuteIfBound(true, TEXT(""));
    return;
    }

    AccelByte::FApiClientPtr ApiClient = UTutorialModuleOnlineUtility::GetApiClient(this);
    if (!ApiClient)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to send upgrade to full account verification code to the registered e-mail. AccelByte API Client is invalid."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString());
    return;
    }

    AccelByte::Api::UserPtr UserApi = ApiClient->GetUserApi().Pin();
    if (!UserApi)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to send upgrade to full account verification code to the registered e-mail. User API is invalid."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString());
    return;
    }

    UserApi->SendUpgradeVerificationCode(
    EmailAddress,
    AccelByte::FVoidHandler::CreateWeakLambda(this, [this, EmailAddress, OnComplete]()
    {
    UE_LOG_REGISTERUSERINGAME(Log, TEXT("Success to send upgrade to full account verification code to the registered e-mail."));
    LastVerificationCodeTargetEmails.Add(EmailAddress);
    OnComplete.ExecuteIfBound(true, TEXT(""));
    }),
    FErrorHandler::CreateWeakLambda(this, [this, OnComplete](int32 ErrorCode, const FString& ErrorMessage)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to send upgrade to full account verification code to the registered e-mail. Error %d: %s"), ErrorCode, *ErrorMessage);
    OnComplete.ExecuteIfBound(false, GetUpgradeAccountErrorMessage((EUpgradeAccountErrorTypes)ErrorCode).ToString());
    })
    );
    }
  4. 次に、事前定義されたDeinitialize()関数を見つけます。この関数は、サブシステムが非初期化されるときに呼び出されます。既存のコードを以下のコードに置き換えて、ヘルパー変数の値をクリアします。

    void URegisterUserInGameSubsystem_Starter::Deinitialize()
    {
    Super::Deinitialize();
    LastVerificationCodeTargetEmails.Empty();
    }

アカウントのアップグレードと認証を実装する

このセクションでは、認証コードを使用してアカウントをアップグレードおよび認証する関数を実装します。

  1. まず、アカウントがすでに完全なアカウントであるかどうかを確認するヘルパー関数を作成します。RegisterUserInGameSubsystem_Starterクラスのヘッダーファイルを開き、以下の関数を宣言します。

    public:
    // ...
    bool IsCurrentUserIsFullAccount();
  2. 次に、RegisterUserInGameSubsystem_StarterクラスのCPPファイルを開き、上記の関数を実装します。この関数は、現在ログインしているアカウントが完全なアカウントであるかどうかを、メールアドレスが登録され認証されているかを確認することでチェックします。

    bool URegisterUserInGameSubsystem_Starter::IsCurrentUserIsFullAccount()
    {
    AccelByte::FApiClientPtr ApiClient = UTutorialModuleOnlineUtility::GetApiClient(this);
    if (!ApiClient)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Cannot get user full account status. AccelByte API Client is invalid."));
    return false;
    }

    const bool bHasLinkedEmail = !ApiClient->CredentialsRef->GetUserEmailAddress().IsEmpty();
    const bool bIsEmailVerified = ApiClient->CredentialsRef->GetAccountUserData().EmailVerified;
    return bHasLinkedEmail && bIsEmailVerified;
    }
  3. RegisterUserInGameSubsystem_Starterクラスのヘッダーファイルに戻り、入力検証のリクエストを送信する新しいヘルパー関数を宣言します。

    public:
    // ...
    void ValidateUserInput(
    const FUserInputValidationRequest& Request,
    const FOnUserInputValidationComplete& OnComplete = FOnUserInputValidationComplete());
  4. 次に、RegisterUserInGameSubsystem_StarterクラスのCPPファイルに以下のコードを追加して、上記の関数を定義します。

    void URegisterUserInGameSubsystem_Starter::ValidateUserInput(
    const FUserInputValidationRequest& Request,
    const FOnUserInputValidationComplete& OnComplete)
    {
    AccelByte::FApiClientPtr ApiClient = UTutorialModuleOnlineUtility::GetApiClient(this);
    if (!ApiClient)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to validate user input. AccelByte API Client is invalid."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString());
    return;
    }

    AccelByte::Api::UserPtr UserApi = ApiClient->GetUserApi().Pin();
    if (!UserApi)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to validate user input. User API is invalid."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString());
    return;
    }

    UserApi->ValidateUserInput(
    Request,
    THandler<FUserInputValidationResponse>::CreateWeakLambda(this, [this, OnComplete](const FUserInputValidationResponse& Result)
    {
    UE_LOG_REGISTERUSERINGAME(Log, TEXT("Success to validate user input."));
    OnComplete.ExecuteIfBound(Result.Valid, Result.Message);
    }),
    FErrorHandler::CreateWeakLambda(this, [this, OnComplete](int32 ErrorCode, const FString& ErrorMessage)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to validate user input. Error %d: %s"), ErrorCode, *ErrorMessage);
    OnComplete.ExecuteIfBound(false, ErrorMessage);
    }));
    }
  5. RegisterUserInGameSubsystem_Starterクラスのヘッダーファイルを再度開き、以下の関数を宣言します。

    public:
    // ...
    void UpgradeAndVerifyAccount(
    const int32 LocalUserNum,
    const FUniqueNetIdPtr UserId,
    const FString& Username,
    const FString& DisplayName,
    const FString& EmailAddress,
    const FString& Password,
    const FString& VerificationCode,
    const FOnUpgradeAndVerifyAccountComplete& OnComplete = FOnUpgradeAndVerifyAccountComplete());
    protected:
    void OnUpgradeAndVerifyAccountSuccess(
    const FAccountUserData& NewFullAccount,
    const int32 LocalUserNum,
    const FUniqueNetIdRef UserId,
    const FOnUpgradeAndVerifyAccountComplete OnComplete);
  6. 次に、RegisterUserInGameSubsystem_StarterクラスのCPPファイルを開き、UpgradeAndVerifyAccount()関数を定義します。この関数は、メールで受信した認証コードを使用してアカウントをアップグレードするリクエストを送信します。リクエストが完了すると、コールバックはOnUpgradeAndVerifyAccountSuccess()関数によって処理されます。

    void URegisterUserInGameSubsystem_Starter::UpgradeAndVerifyAccount(
    const int32 LocalUserNum,
    const FUniqueNetIdPtr UserId,
    const FString& Username,
    const FString& DisplayName,
    const FString& EmailAddress,
    const FString& Password,
    const FString& VerificationCode,
    const FOnUpgradeAndVerifyAccountComplete& OnComplete)
    {
    if (!UserId.IsValid())
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to upgrade headless account to full account. User ID is null."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString(), FAccountUserData());
    return;
    }

    AccelByte::FApiClientPtr ApiClient = UTutorialModuleOnlineUtility::GetApiClient(this);
    if (!ApiClient)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to upgrade headless account to full account. AccelByte API Client is invalid."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString(), FAccountUserData());
    return;
    }

    AccelByte::Api::UserPtr UserApi = ApiClient->GetUserApi().Pin();
    if (!UserApi)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to upgrade headless account to full account. User API is invalid."));
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString(), FAccountUserData());
    return;
    }

    FUpgradeAndVerifyRequest Request;
    Request.Username = Username;
    Request.DisplayName = DisplayName;
    Request.UniqueDisplayName = DisplayName;
    Request.EmailAddress = EmailAddress;
    Request.Password = Password;
    Request.Code = VerificationCode;

    UserApi->UpgradeAndVerify2(
    Request,
    THandler<FAccountUserData>::CreateUObject(this, &ThisClass::OnUpgradeAndVerifyAccountSuccess, LocalUserNum, UserId.ToSharedRef(), OnComplete),
    FErrorHandler::CreateWeakLambda(this, [this, OnComplete](int32 ErrorCode, const FString& ErrorMessage)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to upgrade headless account to full account. Error %d: %s"), ErrorCode, *ErrorMessage);
    OnComplete.ExecuteIfBound(false, GetUpgradeAccountErrorMessage((EUpgradeAccountErrorTypes)ErrorCode).ToString(), FAccountUserData());
    })
    );
    }
  7. 次に、以下のコードを追加してOnUpgradeAndVerifyAccountSuccess()を定義します。このコードは、AGS OSSのユーザーアカウントキャッシュを更新するために、ユーザーアカウント情報を再クエリします。

    void URegisterUserInGameSubsystem_Starter::OnUpgradeAndVerifyAccountSuccess(
    const FAccountUserData& NewFullAccount,
    const int32 LocalUserNum,
    const FUniqueNetIdRef UserId,
    const FOnUpgradeAndVerifyAccountComplete OnComplete)
    {
    UStartupSubsystem* StartupSubsystem = GetWorld()->GetGameInstance()->GetSubsystem<UStartupSubsystem>();
    if (!StartupSubsystem)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to handle on upgrade headless account success. Startup subsystem is null."));
    return;
    }

    AccelByte::FApiClientPtr ApiClient = UTutorialModuleOnlineUtility::GetApiClient(this);
    if (!ApiClient)
    {
    UE_LOG_REGISTERUSERINGAME(Warning, TEXT("Failed to handle on upgrade headless account success.. AccelByte API Client is invalid."));
    return;
    }

    // Query new user info to update account user cache on OSS.
    StartupSubsystem->QueryUserInfo(
    LocalUserNum,
    TPartyMemberArray{ UserId },
    FOnQueryUsersInfoCompleteDelegate::CreateWeakLambda(this, [this, ApiClient, LocalUserNum, UserId, NewFullAccount, OnComplete](
    const FOnlineError& Error,
    const TArray<TSharedPtr<FUserOnlineAccountAccelByte>>& UsersInfo)
    {
    if (!Error.bSucceeded || UsersInfo.IsEmpty())
    {
    UE_LOG_REGISTERUSERINGAME(
    Warning,
    TEXT("Failed to upgrade headless account to full account. Error %s: %s"),
    *Error.ErrorCode,
    *Error.ErrorMessage.ToString());
    OnComplete.ExecuteIfBound(false, UPGRADE_ACCOUNT_UNKNOWN_ERROR.ToString(), FAccountUserData());
    return;
    }

    UE_LOG_REGISTERUSERINGAME(Log, TEXT("Success to upgrade headless account to full account: %s"), *NewFullAccount.DisplayName);

    // Update account user cache on SDK.
    ApiClient->CredentialsRef->SetAccountUserData(NewFullAccount);

    OnComplete.ExecuteIfBound(true, TEXT(""), NewFullAccount);
    }));
    }

リソース