Unreal Engine Module - Store game settings in the cloud - Put it all together
Connect UI with Cloud Save implementation
In this section, you will learn how to connect the Options menu to save and load the game sound options using Cloud Save.
First, you will need to define keys for the records you intend to save/load. In the Byte Wars project, these record keys are already defined in the
/Source/AccelByteWars/TutorialModules/Storage/CloudSaveEssentials/CloudSaveModels.h
header. Go right ahead to the next step.#define GAME_OPTIONS_KEY FString(TEXT("GameOptions"))
#define SOUND_OPTIONS_KEY FString(TEXT("Sound"))
#define SOUND_OPTIONS_MUSIC_KEY FString(TEXT("musicvolume"))
#define SOUND_OPTIONS_SFX_KEY FString(TEXT("sfxvolume"))A Cloud Save record is stored as a pair of string key and JSON object value. The JSON object value is a collection of key and value pairs. In Byte Wars, we use
category-subcategory
format as the key, the category beingGAME_OPTIONS_KEY
and the subcategory beingSOUND_OPTIONS_KEY
. We save the music and SFX volume under the cloud save record which we will represent withSOUND_OPTIONS_MUSIC_KEY
andSOUND_OPTIONS_SFX_KEY
in the record's JSON fields. A basic hierarchy would look something like the code below. Again, you don't need to do anything in this step, go right ahead to the next step.{
GameOptions-Sound:
"musicvolume": <value>,
"sfxvolume": <value>
}Next, let's use those record keys to load the game sound options from Cloud Save. Open the
CloudSaveSubsystem_Starter
class CPP file, navigate toOnLoadGameSoundOptions
function, and add the following code. This will show a loading screen and send a request to get the game options from Cloud Save. Once the request is completed, it then hides the loading screen and updates the game options based on the response from cloud save.void UCloudSaveSubsystem_Starter::OnLoadGameSoundOptions(const APlayerController* PC, TDelegate<void()> OnComplete)
{
if (!PC)
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Cannot get game options from Cloud Save. Player Controller is null."));
return;
}
UAccelByteWarsGameInstance* GameInstance = Cast<UAccelByteWarsGameInstance>(GetGameInstance());
ensure(GameInstance);
UPromptSubsystem* PromptSubsystem = GameInstance->GetSubsystem<UPromptSubsystem>();
ensure(PromptSubsystem);
PromptSubsystem->ShowLoading();
// Get game options from Cloud Save.
GetPlayerRecord(
PC,
FString::Printf(TEXT("%s-%s"), *GAME_OPTIONS_KEY, *SOUND_OPTIONS_KEY),
FOnGetCloudSaveRecordComplete::CreateWeakLambda(this, [this, GameInstance, PromptSubsystem, OnComplete](bool bWasSuccessful, FJsonObject& Result)
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Get game options from Cloud Save was successful: %s"), bWasSuccessful ? TEXT("True") : TEXT("False"));
PromptSubsystem->HideLoading();
// Update the local game options based on the Cloud Save record.
if (bWasSuccessful)
{
GameInstance->SetMusicVolume(Result.GetNumberField(SOUND_OPTIONS_MUSIC_KEY));
GameInstance->SetSFXVolume(Result.GetNumberField(SOUND_OPTIONS_SFX_KEY));
}
OnComplete.ExecuteIfBound();
})
);
}Now, we will move on to saving the sound options to Cloud Save. Navigate to the definition of the
OnSaveGameSoundOptions
method in the class CPP file and add the following code. This will show a loading screen and send a request to set the game options in the Cloud Save record. Once the request is completed, it then hides the loading screen.void UCloudSaveSubsystem_Starter::OnSaveGameSoundOptions(const APlayerController* PC, TDelegate<void()> OnComplete)
{
if (!PC)
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Cannot set game options from Cloud Save. Player Controller is null."));
return;
}
UAccelByteWarsGameInstance* GameInstance = Cast<UAccelByteWarsGameInstance>(GetGameInstance());
ensure(GameInstance);
UPromptSubsystem* PromptSubsystem = GameInstance->GetSubsystem<UPromptSubsystem>();
ensure(PromptSubsystem);
PromptSubsystem->ShowLoading(LOCTEXT("Saving", "Saving"));
// Construct game options to save.
FJsonObject GameOptionsData;
GameOptionsData.SetNumberField(SOUND_OPTIONS_MUSIC_KEY, GameInstance->GetMusicVolume());
GameOptionsData.SetNumberField(SOUND_OPTIONS_SFX_KEY, GameInstance->GetSFXVolume());
// Save the game options to Cloud Save.
SetPlayerRecord(
PC,
FString::Printf(TEXT("%s-%s"), *GAME_OPTIONS_KEY, *SOUND_OPTIONS_KEY),
GameOptionsData,
FOnSetCloudSaveRecordComplete::CreateWeakLambda(this, [this, PromptSubsystem, OnComplete](bool bWasSuccessful)
{
UE_LOG_CLOUDSAVE_ESSENTIALS(Warning, TEXT("Set game options from Cloud Save was successful: %s"), bWasSuccessful ? TEXT("True") : TEXT("False"));
PromptSubsystem->HideLoading();
OnComplete.ExecuteIfBound();
}
));
}Next, we want to bind our
OnLoadGameSoundOptions
andOnSaveGameSoundOptions
methods to the Options menu opening and closing. To do this, we will bind those two methods to theOnOptionsWidgetActivated
andOnOptionsWidgetDeactivated
delegates from the Options widget. To do so, add the following code to theBindDelegates
method in theCloudSaveSubsystem_Starter
class CPP file.void UCloudSaveSubsystem_Starter::BindDelegates()
{
UOptionsWidget::OnOptionsWidgetActivated.AddUObject(this, &ThisClass::OnLoadGameSoundOptions);
UOptionsWidget::OnOptionsWidgetDeactivated.AddUObject(this, &ThisClass::OnSaveGameSoundOptions);
}Finally, we want to unbind the delegates mentioned above when the cloud save subsystem is destroyed. This can be done with the following code in the
UnbindDelegates
method in theCloudSaveSubsystem_Starter
class CPP file.void UCloudSaveSubsystem_Starter::UnbindDelegates()
{
UOptionsWidget::OnOptionsWidgetActivated.RemoveAll(this);
UOptionsWidget::OnOptionsWidgetDeactivated.RemoveAll(this);
}Congratulations! You have connected the Options menu to load/save game sound options from/to Cloud Save using the
CloudSaveSubsystem_Starter
.
Resources
- The files used in this tutorial section are available in the Byte Wars GitHub repository.
- AccelByteWars/Source/AccelByteWars/TutorialModules/Storage/CloudSaveEssentials/CloudSaveModels.h
- AccelByteWars/Source/AccelByteWars/TutorialModules/Storage/CloudSaveEssentials/CloudSaveSubsystem_Starter.h
- AccelByteWars/Source/AccelByteWars/TutorialModules/Storage/CloudSaveEssentials/CloudSaveSubsystem_Starter.cpp