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

クラウドセーブを使用して機能フラグを実装する

Last updated on February 4, 2026

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

概要

AccelByte Gaming Services (AGS) のクラウドセーブを使用すると、ゲームのアップデートを必要とせずに、特定の機能をリモートで有効または無効にすることができます。このガイドでは、これらの機能フラグをゲームに実装し、AGS 管理ポータルでオン/オフを切り替える方法を説明します。

前提条件

AGS Online Subsystem (OSS) バージョン 0.12.0 および AGS Game SDK Unreal 24.7.0 以降がインストールされている必要があります。

また、ゲームレコードでのゲーム内設定をセットアップする必要があります。

このガイドでは、Unreal Engine v5.1 で Byte Wars を使用しますので、一緒に進めたい場合は必要なファイルをクローンしてインストールしてください。Unreal Engine Byte Wars の GitHub はこちらにあり、Byte Wars Unreal でクラウドセーブを起動して実行するためのチュートリアルはこちらにあります。

ゲームレコードのクラウドセーブを実装する

このセクションでは、ゲームレコードのクラウドセーブを実装する手順を説明します。

プロジェクトの .ini ファイルにゲーム設定フラグを作成します。この例では、EnableMatchmakingEnableStore フラグを作成し、DefaultEngine.ini ファイルで true に設定します。

    [GameConfig]
EnableMatchmaking=true
EnableStore=true

Byte Wars モジュールを使用している場合、ゲームレコードはまだ実装されていません。実装するには、次の手順に従ってください。

CloudSaveSubsystem.h に次のコードを追加します:

public:
void GetGameRecord(const APlayerController* PlayerController, const FString& RecordKey, const FOnGetCloudSaveRecordComplete& OnGetRecordComplete);


private:
void OnGetGameRecordComplete(int32 LocalUserNum, const FOnlineError& Result, const FString& Key, const FAccelByteModelsGameRecord& GameRecord, const FOnGetCloudSaveRecordComplete OnGetRecordComplete);


FDelegateHandle OnGetGameRecordCompletedDelegateHandle;

このコードを CloudSaveSubsystem.cppUCloudSaveSubsystem::GetGameRecord 宣言に追加します:

void UCloudSaveSubsystem::GetGameRecord(const APlayerController* PlayerController, const FString& RecordKey, const FOnGetCloudSaveRecordComplete& OnGetRecordComplete)
{
if (!ensure(CloudSaveInterface.IsValid()))
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Cloud Save interface is not valid."));
return;
}


const ULocalPlayer* LocalPlayer = PlayerController->GetLocalPlayer();
ensure(LocalPlayer != nullptr);
int32 LocalUserNum = LocalPlayer->GetControllerId();


OnGetGameRecordCompletedDelegateHandle = CloudSaveInterface->AddOnGetGameRecordCompletedDelegate_Handle(LocalUserNum, FOnGetGameRecordCompletedDelegate::CreateUObject(this, &ThisClass::OnGetGameRecordComplete, OnGetRecordComplete));
CloudSaveInterface->GetGameRecord(LocalUserNum, RecordKey);
}

このコードを CloudSaveSubsystem.cppUCloudSaveSubsystem::OnGetGameRecordComplete 宣言に追加します:

void UCloudSaveSubsystem::OnGetGameRecordComplete(int32 LocalUserNum, const FOnlineError& Result, const FString& Key, const FAccelByteModelsGameRecord& GameRecord, const FOnGetCloudSaveRecordComplete OnGetRecordComplete)
{
FJsonObject RecordResult;


if (Result.bSucceeded)
{
RecordResult = GameRecord.Value.JsonObject.ToSharedRef().Get();
UE_LOG_CLOUDSAVE_ESSENTIALS(Log, TEXT("Success to get game record."));
}
else
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Log, TEXT("Failed to get game record. Message: %s"), *Result.ErrorMessage.ToString());
}


CloudSaveInterface->ClearOnGetGameRecordCompletedDelegate_Handle(LocalUserNum, OnGetGameRecordCompletedDelegateHandle);
OnGetRecordComplete.ExecuteIfBound(Result.bSucceeded, RecordResult);
}

後でクラウドセーブから取得する際に使用するゲーム設定フラグ用に、以下の定義文字列を作成します。

#define GAME_CONFIG_KEY FString(TEXT("GameConfig"))
#define ENABLE_MATCHMAKING_KEY FString(TEXT("enableMatchmaking"))
#define ENABLE_STORE_KEY FString(TEXT("enableStore"))

ゲーム設定を実装する

次に、ゲーム設定を実装します。先ほど作成したゲーム設定値を DefaultEngine.ini から次のコードを使用して取得できます:

bool bEnableMatchmaking;
GConfig->GetBool(TEXT("GameConfig"), TEXT("EnableMatchmaking"), bEnableMatchmaking, GEngineIni);


bool bEnableStore;
GConfig->GetBool(TEXT("GameConfig"), TEXT("EnableStore"), bEnableStore, GEngineIni);

また、常に DefaultEngine.ini ファイルから読み取る代わりに、ゲーム設定値を変数に保存することもできます。

このコードを AccelByteWarsGameInstance.h に追加します:

public:
void SetEnableMatchmaking(bool InValue);
void SetEnableStore(bool InValue);


bool GetEnableMatchmaking();
bool GetEnableStore();


private:
bool bEnableMatchmaking = false;
bool bEnableStore = false;

次に、このコードを AccelByteWarsGameInstance.cpp に追加します:

void UAccelByteWarsGameInstance::SetEnableMatchmaking(bool InValue)
{
bEnableMatchmaking = InValue;
}


void UAccelByteWarsGameInstance::SetEnableStore(bool InValue)
{
bEnableStore = InValue;
}


bool UAccelByteWarsGameInstance::GetEnableMatchmaking()
{
return bEnableMatchmaking;
}


bool UAccelByteWarsGameInstance::GetEnableStore()
{
return bEnableStore;
}

これで、DefaultEngine.ini ファイルからゲーム設定値を、ゲームインスタンスで作成した新しい値に保存できます。Byte Wars を使用している場合は、LoginWidget.cppULoginWidget::NativeOnActivated() に追加できます。

bool bEnableMatchmaking;
GConfig->GetBool(TEXT("GameConfig"), TEXT("EnableMatchmaking"), bEnableMatchmaking, GEngineIni);
GameInstance->SetEnableMatchmaking(bEnableMatchmaking);


bool bEnableStore;
GConfig->GetBool(TEXT("GameConfig"), TEXT("EnableStore"), bEnableStore, GEngineIni);
GameInstance->SetEnableStore(bEnableStore);

AGS 管理ポータルで作成したゲームレコードを取得するには、UCloudSaveSubsystem::GetGameRecord を呼び出すことができますが、プレイヤーが AGS にログインした後に呼び出すようにしてください。

Byte Wars では、これを LoginWidget クラスに追加できます。LoginWidget.h に次を追加します。

#include "Storage/CloudSaveEssentials/CloudSaveSubsystem.h"


protected:
void OnLoadGameConfigFromCloud(const APlayerController* PlayerController, FSimpleDelegate OnComplete);


private:
UCloudSaveSubsystem* CloudSaveSubsystem;

LoginWidget.cpp で、先ほど作成した CloudSaveSubsystem から GetGameRecord を呼び出します:

void ULoginWidget::OnLoadGameConfigFromCloud(const APlayerController* PlayerController, FSimpleDelegate OnComplete)
{
if (!PlayerController)
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Cannot get game config from Cloud Save. Player Controller is null."));
return;
}


// Get game config from Cloud Save.
CloudSaveSubsystem = GameInstance->GetSubsystem<UCloudSaveSubsystem>();
CloudSaveSubsystem->GetGameRecord(
PlayerController,
GAME_CONFIG_KEY, //FString with value of GameConfig
FOnGetCloudSaveRecordComplete::CreateWeakLambda(this, [this, OnComplete](bool bWasSuccessful, FJsonObject& Result)
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Get game config from Cloud Save was successful: %s"), bWasSuccessful ? TEXT("True") : TEXT("False"));


// Update the local game options based on the Cloud Save record.
if (bWasSuccessful)
{
// Get game config from DefaultEngine.ini
bool bEnableMatchmaking = Result.GetBoolField(ENABLE_MATCHMAKING_KEY); // FString with value of enableMatchmaking
GConfig->SetBool(TEXT("GameConfig"), TEXT("EnableMatchmaking"), bEnableMatchmaking, GEngineIni);
GameInstance->SetEnableMatchmaking(bEnableMatchmaking);


bool bEnableStore = Result.GetBoolField(ENABLE_STORE_KEY); //FString with value of enableStore
GConfig->SetBool(TEXT("GameConfig"), TEXT("EnableStore"), bEnableStore, GEngineIni);
GameInstance->SetEnableStore(bEnableStore);
}


OnComplete.ExecuteIfBound();
})
);
}

次のコードを使用してゲーム設定値を取得できます:

bool bEnableMatchmaking = Result.GetBoolField(ENABLE_MATCHMAKING_KEY);
bool bEnableStore = Result.GetBoolField(ENABLE_STORE_KEY);

次に、DefaultEngine.ini に保存できます。これはランタイムキャッシュのみであるため、実際のファイルは変更されません。

GConfig->SetBool(TEXT("GameConfig"), TEXT("EnableMatchmaking"), bEnableMatchmaking, GEngineIni);
GConfig->SetBool(TEXT("GameConfig"), TEXT("EnableStore"), bEnableStore, GEngineIni);

後で使用するために、ゲームインスタンスに保存します。

GameInstance->SetEnableMatchmaking(bEnableMatchmaking);
GameInstance->SetEnableStore(bEnableStore);

フリーフォームプッシュ通知を追加する

ゲーム設定の変更を通知するロビー通知のリスナーを作成する必要があります。まず、AGS 管理ポータルでトピックを作成します。この例では、GAMECONFIG_CHANGE トピックを作成します。AGS 管理ポータルでゲームのネームスペースを開き、ソーシャル > プッシュ通知 > トピックに移動します。+ 新しいトピックをクリックします。トピック名を GAMECONFIG_CHANGE として入力し、説明を追加します。

ゲームプロジェクトでは、通知のリスナーを追加する必要があります。まず、ApiClient を取得する必要があります。このコードを AuthEssentialsSubsystem.h に追加します:

public:
AccelByte::FApiClientPtr GetApiClient();


private:
AccelByte::FApiClientPtr ApiClient;

このコードを AuthEssentialsSubsystem.cpp に追加します:

AccelByte::FApiClientPtr UAuthEssentialsSubsystem::GetApiClient()
{
if (!ApiClient.IsValid())
{
UE_LOG_AUTH_ESSENTIALS(Warning, TEXT("Api Client not valid"));
return nullptr;
}
return ApiClient;
}

ログインが成功したときに、UAuthEssentialsSubsystem::OnLoginCompleteApiClient を設定します:

if (bLoginWasSuccessful)
{
UE_LOG_AUTH_ESSENTIALS(Log, TEXT("Login user successful."));
ApiClient = IdentityInterface->GetApiClient(LocalUserNum);


if (!ApiClient.IsValid())
{
UE_LOG_AUTH_ESSENTIALS(Warning, TEXT("Cannot get the Api Client"));
}
}
else

次に、LoginWidget.h で通知用の関数デリゲートを作成します:

void OnMessageNotif(const FAccelByteModelsNotificationMessage& InMessage);

そして、LoginWidget.cpp にその宣言を追加します。

void ULoginWidget::OnMessageNotif(const FAccelByteModelsNotificationMessage& InMessage)
{
if (InMessage.Topic == "GAMECONFIG_CHANGE")
{
// do hide the corresponding button
}
}

ユーザーログインが完了した後、LoginWidget.cppULoginWidget::OnLoginComplete でデリゲート関数を設定します:

const AccelByte::FApiClientPtr ApiClient = AuthSubsystem->GetApiClient();


// listen to Message Notif Lobby
const AccelByte::Api::Lobby::FMessageNotif Delegate = AccelByte::Api::Lobby::FMessageNotif::CreateUObject(this, &ULoginWidget::OnMessageNotif);
if (!ApiClient.IsValid())
{
UE_LOG_AUTH_ESSENTIALS(Warning, TEXT("Cannot get the Api Client"));
return;
}
ApiClient->Lobby.SetMessageNotifDelegate(Delegate);

プッシュ通知を送信するには、AGS 管理ポータルのソーシャル > プッシュ通知 > テンプレートに移動し、フリーフォームを送信をクリックします。

Send Freeform Push Notification on Admin Portal

UI ボタンを処理する

Byte Wars プロジェクトでは、メインメニューの UI ボタンを処理するものがありません。まず追加する必要があるので、AccelByteWarsGameInstance.h に戻り、このコードを追加します:

public:
void SetPlayOnlineButton(UUserWidget* InButton);
void SetStoreButton(UUserWidget* InButton);


void SetPlayOnlineButtonVisibility(ESlateVisibility InValue);
void SetStoreButtonVisibility(ESlateVisibility InValue);

private:
UUserWidget* ButtonPlayOnline;
UUserWidget* ButtonStore;

次に、AccelByteWarsGameInstance.cpp でその関数の宣言を作成します。

void UAccelByteWarsGameInstance::SetPlayOnlineButton(UUserWidget* InButton)
{
ButtonPlayOnline = InButton;
}


void UAccelByteWarsGameInstance::SetStoreButton(UUserWidget* InButton)
{
ButtonStore = InButton;
}


void UAccelByteWarsGameInstance::SetPlayOnlineButtonVisibility(ESlateVisibility InValue)
{
if (!ButtonPlayOnline)
{
GAMEINSTANCE_LOG("Failed to Set Play Online Button Visibility, the button is not set");
return;
}
ButtonPlayOnline->SetVisibility(InValue);
}


void UAccelByteWarsGameInstance::SetStoreButtonVisibility(ESlateVisibility InValue)
{
if (!ButtonPlayOnline)
{
GAMEINSTANCE_LOG("Failed to Set Store Button Visibility, the button is not set");
return;
}
ButtonStore->SetVisibility(InValue);
}

その後、AccelByteWarsActivatableWidget.cppUAccelByteWarsActivatableWidget::GenerateEntryButton にこのコードを追加して、Play OnlineStore ボタンを設定します:

if (EntryWidgetClassName == "W_PlayOnline_C")
{
GameInstance->SetPlayOnlineButton(Button.Get());
}


if (EntryWidgetClassName == "W_Store_C")
{
GameInstance->SetStoreButton(Button.Get());
}

LoginWidget.h で、設定に基づいて対応するボタンを表示または非表示にするゲーム設定更新を処理する関数デリゲートを作成します:

public:
void UpdateConfig();


private:
FSimpleDelegate OnGetGameRecordComplete;

LoginWidget.cpp にその宣言を追加します。

void ULoginWidget::UpdateConfig()
{
if (GameInstance->GetEnableMatchmaking())
{
GameInstance->SetPlayOnlineButtonVisibility(ESlateVisibility::Visible);
}
else
{
GameInstance->SetPlayOnlineButtonVisibility(ESlateVisibility::Collapsed);
}


if (GameInstance->GetEnableStore())
{
GameInstance->SetStoreButtonVisibility(ESlateVisibility::Visible);
}
else
{
GameInstance->SetStoreButtonVisibility(ESlateVisibility::Collapsed);
}
}

これで、OnGetGameRecordCompleteUpdateConfig にバインドできます。ULoginWidget::NativeOnActivated にこのコードを追加します:

OnGetGameRecordComplete.BindUObject(this, &ULoginWidget::UpdateConfig);

次に、先ほど追加した OnLoadGameConfigFromCloud 関数を LoginWidget.cppULoginWidget::OnLoginComplete に呼び出して、すべてをまとめます。プレイヤーが正常にログインしたときのために、このコードを追加します:

APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
ensure(PlayerController);


OnLoadGameConfigFromCloud(PlayerController, OnGetGameRecordComplete);

そして、ULoginWidget::OnMessageNotif にこのコードを追加します:

if (InMessage.Topic == "GAMECONFIG_CHANGE")
{
OnLoadGameConfigFromCloud(GetOwningPlayer(), OnGetGameRecordComplete);
}

結果を確認する

ゲームを実行して結果を確認します。AGS 管理ポータルで作成したゲーム設定を変更して、Play Online および/または Store ボタンを有効または無効にできます。DefaultEngine.ini を介してゲーム設定のデフォルト値を指定できます。

[GameConfig]
EnableMatchmaking=true
EnableStore=true

または、ゲームレコードのクラウドセーブとフリーフォームプッシュ通知を使用して、その場で値を変更できます。

Game Config on Game Record Admin Portal

これは、マッチメイキングとストアが有効になっている Byte Wars のメインメニューです:

Game Config All On

これは、ゲーム設定からマッチメイキングが無効になっている Byte Wars のメインメニューです:

Game Config Matchmaking off

これは、ゲーム設定からストアが無効になっている Byte Wars のメインメニューです。

Game Config Store off

そして、これは、ゲーム設定からマッチメイキングとストアが無効になっている Byte Wars のメインメニューです。

Game Config All Off