La signification de "sauvegarde" peut varier d'un jeu à l'autre. Dans la plupart des jeux modernes, l'idée générale reste cependant de permettre aux joueurs de quitter le jeu, puis de le reprendre au même endroit. En fonction du type de jeu, vous pouvez n'avoir besoin que de quelques informations de base, comme le dernier point de contrôle atteint par le joueur et les objets qu'il a trouvés. Vous pouvez également avoir besoin d'informations bien plus détaillées, notamment une liste des interactions sociales du joueur avec d'autres personnages dans le jeu, ou encore le statut de diverses quêtes, objectifs de mission ou intrigues secondaires.
L'Unreal Engine (UE) est doté d'un système de sauvegarde et de chargement qui s'articule autour d'une ou plusieurs classes SaveGame personnalisées que vous devez créer pour répondre aux besoins spécifiques de votre jeu, y compris toutes les informations à conserver sur plusieurs sessions de jeu. Le système permet de créer plusieurs fichiers de sauvegarde et de sauvegarder différentes classes SaveGame dans ces fichiers. Ceci est particulièrement utile pour séparer les fonctionnalités déverrouillées de manière globale des données spécifiques à une partie.
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;
}Sauvegarder un jeu
Une fois que vous avez créé la classe SaveGame, vous pouvez l'agrémenter de variables afin de stocker les données de votre jeu. Par exemple, vous pouvez créer une variable de nombre entier pour stocker le score du joueur ou une variable de chaîne pour stocker son nom. Lorsque vous sauvegardez le jeu, ces informations sont transférées du monde de jeu actuel vers un objet SaveGame. Lors du chargement d'un jeu, elles sont copiées de l'objet SaveGame vers un objet de jeu tel que des personnages, le contrôleur de joueur ou le mode de jeu.
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.
}Sur les plateformes de développement, les fichiers de sauvegarde portent l'extension .sav et apparaissent dans le dossier Saved\SaveGames du projet. Sur d'autres plateformes, particulièrement sur les consoles, cela varie selon le système de fichier.
Charger un jeu
Pour charger une partie sauvegardée, vous devez renseigner le nom d'emplacement et l'identifiant utilisateur utilisés lors de la sauvegarde. Si l'objet SaveGame spécifié existe, le moteur le remplit à l'aide des données qu'il contient et le renvoie en tant qu'objet SaveGame de base (classe USaveGame). Vous pouvez ensuite projeter cet objet vers votre classe SaveGame personnalisée et accéder aux données. En fonction des données que contient votre SaveGame, vous pouvez avoir besoin d'en conserver une copie. Il peut également suffire d'utiliser les données, puis de se débarrasser de l'objet.
Comme pour la sauvegarde, il est possible de charger de manière synchrone ou asynchrone. Si vous disposez d'une grande quantité de données ou si vous souhaitez utiliser un écran ou une animation de chargement, nous vous recommandons la méthode asynchrone. Pour les petites quantités de données qui chargent rapidement, il existe une méthode synchrone.
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).
}