Die Bedeutung von "Das Spiel speichern" kann sich von Spiel zu Spiel stark unterscheiden, aber allgemein bedeutet es, den Spielern zu erlauben, das Spiel zu verlassen und später wieder dort anzufangen, wo sie aufgehört haben. Die meisten modernen Spiele verfügen über diese Funktion. Abhängig davon, welche Art von Spiel Sie erstellen, benötigen Sie mitunter nur einige sehr grundlegende Informationen, darunter den letzten Kontrollpunkt, den der Spieler erreicht hat, sowie vielleicht Informationen, welche Gegenstände der Spieler gefunden hat. Vielleicht benötigen Sie aber auch umfassendere Informationen, etwa eine lange Liste aller sozialen Interaktionen des Spielers mit anderen Charakteren im Spiel, oder den aktuellen Status einer Reihe von Quests, Missionszielen oder Nebengeschichten.
Die Unreal Engine (UE) bietet ein System zum Speichern und Laden, das auf einer oder mehreren benutzerdefinierten SaveGame-Klassen aufbaut, die Sie erstellen, um die speziellen Anforderungen Ihres Spiels zu erfüllen, einschließlich aller Informationen, die Sie zwischen den einzelnen Spielsitzungen erhalten müssen. Das System unterstützt die Fähigkeit, mehrere gespeicherte Spieldateien anzulegen und in diesen Dateien verschiedene SaveGame-Klassen zu speichern. Dies ist nützlich, um übergreifend freigeschaltete Funktionen von Spieldaten zu trennen, die sich von Spieldurchgang zu Spieldurchgang unterscheiden.
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;
}Ein Spiel speichern
Sobald Sie eine SaveGame-Klasse erstellt haben, können Sie diese mit Variablen füllen, um die Daten Ihres Spiels zu speichern. Beispielsweise können Sie eine Ganzzahl Variable erstellen, um den Punktestand eines Spielers zu speichern, oder eine String Variable für den Namen des Spielers. Wenn Sie das Spiel speichern, übertragen Sie diese Informationen aus der aktuellen Spielwelt in ein SaveGame-Objekt, und beim Laden des Spiels kopieren Sie diese vom SaveGame-Objekt zu den entsprechenden Spielobjekten, beispielsweise Charaktere, Player-Controller oder Spiel-Modus.
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.
}Auf Entwicklungsplattformen verwenden gespeicherte Spiel-Dateien die .sav-Datei Erweiterung im Ordner Gespeichert\SaveGames des Projekts. Auf anderen Plattformen, insbesondere Konsolen, hängt das vom jeweiligen Datei-System ab.
Ein Spiel laden
Um ein gespeichertes Spiel zu laden, müssen Sie den Namen des Speicherplatzes und die Nutzer-ID angeben, die Sie beim Speichern genutzt haben. Wenn das von Ihnen angegebene SaveGame existiert, füllt die Engine Ihr SaveGame-Objekt mit den Daten, die es enthält, und gibt es als einfaches SaveGame-Objekt (Klasse USaveGame) aus. Sie können dieses Objekt dann zurück in Ihre benutzerdefinierte SaveGame-Klasse casten und auf die Daten zugreifen. Abhängig davon, welche Art Daten Ihr SaveGame-Typ enthält, sollten Sie eventuell eine Kopie davon behalten oder einfach die Daten nutzen und das Objekt verwerfen.
Das Laden ist wie das Speichern synchron und asynchron möglich. Wenn Sie eine große Menge Daten haben oder beim Laden einen Ladebildschirm oder eine Animation anzeigen wollen, empfehlen wir die asynchrone Methode. Bei kleinen Datenmengen, die schnell geladen werden, steht eine synchrone Methode zur Verfügung.
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).
}