「ゲームを保存する」という意味はゲームごとに大きく異なりますが、一般的には、プレイヤーがゲームを終了し、その後、中断したところから再開できるようにするという考え方であり、ほとんどの最新ゲームに共通しています。 開発しているゲームの種類によっては、プレイヤーが到達した最終チェックポイントや、プレイヤーが見つけたアイテムなど、いくつかの基本的な情報を保存するだけで十分です。 また、プレイヤーと他のゲーム内キャラクターとのソーシャル インタラクションの詳細リストや、さまざまなクエスト、ミッションの目的、サブプロットの現在のステータスなど、さらに詳しい情報が必要になることもあります。
Unreal Engine (UE) には、複数のプレイセッションにわたって保存する必要があるすべての情報を含む、ゲーム固有のニーズに合わせて作成する 1 つ以上のカスタム SaveGame クラスを中心とした保存および読み込みシステムが搭載されています。 システムでは、複数の保存済みゲーム ファイルを持つ機能と、異なる SaveGame クラスをそれらのファイルに保存する機能がサポートされています。 これは、グローバルにロック解除された機能とプレイスルー固有のゲーム データを分離するのに便利です。
Creating a SaveGame Object
The USaveGame class sets up an object that can be used as a target for the saving and loading functions declared in Kismet/GameplayStatics.h.
You can create a new class based on USaveGame using the C++ Class Wizard.
In this example, the new USaveGame class is called UMySaveGame. In order to use it, add the following lines to your game module's header file, after any other #include directives:
#include "MySaveGame.h"
#include "Kismet/GameplayStatics.h"Header
In the header file for your SaveGame object, you can declare any variables you want your SaveGame to store.
UPROPERTY(VisibleAnywhere, Category = Basic)
FString PlayerName;In this example, there are also variables declared that will be used to store default values for the SaveSlotName and the UserIndex, so that each class that saves to this
SaveGame object will not have to independently set those variables. This step is optional, and will cause there to be one save slot that gets overwritten if the default values are not changed.
#pragma once
#include "GameFramework/SaveGame.h"
#include "MySaveGame.generated.h"
/**
*
*/
UCLASS()
class [PROJECTNAME]_API UMySaveGame : public USaveGame
Source
Generally, the SaveGame object's source file does not need any particular code to function, unless your particular save system has additional functionality you would like to set up
here.
This example does define the values of SaveSlotName and UserIndex in the class constructor, so they can be read out and used by other gameplay classes.
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "[ProjectName].h"
#include "MySaveGame.h"
UMySaveGame::UMySaveGame()
{
SaveSlotName = TEXT("TestSaveSlot");
UserIndex = 0;
}ゲームを保存
SaveGame クラスを作成したら、このクラスに変数を追加して、ゲームのデータを保存することができます。 たとえば、プレイヤーのスコアを保存する整数変数や、プレイヤーの名前を保存する文字列変数を作成することができます。 ゲームを保存するとき、その情報を、現在のゲーム ワールドから SaveGame オブジェクトに転送し、ゲームをロードするとき、その情報を、SaveGame オブジェクトからキャラクター、プレイヤー コントローラー、ゲーム モードなどのゲーム オブジェクトにコピーします。
First, call CreateSaveGameObject (from the UGameplayStatics library) to get a new UMySaveGame object. Once you have the object, you can populate it with the data you want to save. Finally, call SaveGameToSlot or AsyncSaveGameToSlot to write the data out to your device.
Asynchronous Saving
AsyncSaveGameToSlot is the recommended method for saving the game. Running asynchronously prevents a sudden framerate hitch, making it less noticeable to players and avoiding a possible certification issue on some platforms. When the save process is complete, the delegate (of type FAsyncSaveGameToSlotDelegate) will be called with the slot name, the user index, and a bool indicating success or failure.
if (UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass())))
{
// Set up the (optional) delegate.
FAsyncSaveGameToSlotDelegate SavedDelegate;
// USomeUObjectClass::SaveGameDelegateFunction is a void function that takes the following parameters: const FString& SlotName, const int32 UserIndex, bool bSuccess
SavedDelegate.BindUObject(SomeUObjectPointer, &USomeUObjectClass::SaveGameDelegateFunction);
// Set data on the savegame object.
SaveGameInstance->PlayerName = TEXT("PlayerOne");
Synchronous Saving
SaveGameToSlot is sufficient for small SaveGame formats, and for saving the game while paused or in a menu. It's also easy to use, as it simply saves the game immediately and returns a bool indicating success or failure. For larger amounts of data, or for auto-saving game while the player is still actively interacting with your game world, AsyncSaveGameToSlot is a better choice.
if (UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass())))
{
// Set data on the savegame object.
SaveGameInstance->PlayerName = TEXT("PlayerOne");
// Save the data immediately.
if (UGameplayStatics::SaveGameToSlot(SaveGameInstance, SlotNameString, UserIndexInt32))
{
// Save succeeded.
}
Binary Saving
You can transfer a SaveGame object to memory with the SaveGameToMemory function. This function only offers synchronous operation, but is faster than saving to a drive. The caller provides a reference to a buffer (a TArray<uint8>&) where the data will be stored. On success, the function returns true.
TArray<uint8> OutSaveData;
if (UGameplayStatics::SaveGameToMemory(SaveGameObject, OutSaveData))
{
// The operation succeeded, and OutSaveData now contains a binary represenation of the SaveGame object.
}You can also save binary data directly to a file, similar to the SaveGameToSlot function, by calling SaveDataToSlot with the buffer (a const TArray<uint8>&) and the slot name and user ID information. As with SaveGameToMemory, this function only offers synchronous operation, and returns a bool to indicate success or failure.
if (UGameplayStatics::SaveDataToSlot(InSaveData, SlotNameString, UserIndexInt32))
{
// The operation succeeded, and InSaveData has been written to the save file defined by the slot name and user ID we provided.
}開発プラットフォームでは、保存済みのゲーム ファイルが .sav 拡張子を使用し、プロジェクトの Saved\SaveGames フォルダに表示されます。 他のプラットフォーム、特にコンソールでは、特定のファイルシステムに合わせて拡張子が異なります。
ゲームをロード
保存したゲームをロードするには、保存時に使用したセーブ スロット名とユーザー ID を指定する必要があります。 指定した SaveGame が存在する場合、エンジンはその SaveGame オブジェクトに含まれているデータを設定し、それを基本 SaveGame (クラス USaveGame) オブジェクトとして返します。 次に、そのオブジェクトをカスタム SaveGame クラスにキャストし直すと、データにアクセスできます。 SaveGame 型に含まれているデータの種類によって、そのコピーを保持するか、データを使用してオブジェクトを破棄することができます。
保存と同様に、ロードの同期/非同期も可能です。 大量のデータがある場合や、ロード時にロード画面やアニメーションを使用する場合は、非同期メソッドをおすすめします。 短時間でロードされる少量のデータに対しては、同期メソッドがあります。
Asynchronous Loading
When loading asynchronously with AsyncLoadGameFromSlot, you must provide a callback delegate in order to receive the data that the system loads.
// Set up the delegate.
FAsyncLoadGameFromSlotDelegate LoadedDelegate;
// USomeUObjectClass::LoadGameDelegateFunction is a void function that takes the following parameters: const FString& SlotName, const int32 UserIndex, USaveGame* LoadedGameData
LoadedDelegate.BindUObject(SomeUObjectPointer, &USomeUObjectClass::LoadGameDelegateFunction);
UGameplayStatics::AsyncLoadGameFromSlot(SlotName, 0, LoadedDelegate);Synchronous Loading
The LoadGameFromSlot function will create and return a USaveGame object if it succeeds.
// Retrieve and cast the USaveGame object to UMySaveGame.
if (UMySaveGame* LoadedGame = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(SlotName, 0)))
{
// The operation was successful, so LoadedGame now contains the data we saved earlier.
UE_LOG(LogTemp, Warning, TEXT("LOADED: %s"), *LoadedGame->PlayerName);
}Binary Loading
You can load SaveGame data from a file in raw, binary form with LoadDataFromSlot. This function is very similar to LoadGameFromSlot, except that it does not create a SaveGame object. Only synchronous operation is available for this type of loading.
TArray<uint8> OutSaveData;
if (UGameplayStatics::LoadDataFromSlot(OutSaveData, SlotNameString, UserIndexInt32))
{
// The operation succeeded, and OutSaveData now contains a binary represenation of the SaveGame object.
}You can also convert this binary data to a SaveGame object by calling LoadGameFromMemory. This is a synchronous call, and returns a new USaveGame object upon success, or a null pointer on failure.
if (UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(LoadGameFromMemory(InSaveData)))
{
// The operation succeeded, and SaveGameInstance was able to cast to type we expected (UMySaveGame).
}