Saving and loading using binary data.

Unreal Engine provides a API for saving and loading data using the SaveGame class. Using the default class however is somewhat limited. It is good for saving and loading a specific overall values but it is very hard to maintain when you need to save and load specific variables inside a Actor. This is where saving using binary comes very handy! I found out about binary saving by looking up Orfeasels webpage, so big thanks to him! In this tutorial, we are saving the location and rotation of our First Person character so we can load it up later!

Starting up

So let’s go and create a C++ project using the First Person Template. After the project is loaded we go to header file and create some variables and a function to private section.

// Data To Save!
  UPROPERTY(EditAnywhere, BlueprintReadWrite)
  FVector PlayerLocation;

  UPROPERTY(EditAnywhere, BlueprintReadWrite)
  FRotator PlayerRotation;

// Archive to send data back and forth
  void SaveLoadData(FArchive& Ar, FVector& PlayerLocationToSaveOrLoad, FRotator& PlayerRotationToSaveOrLoad);

Next, in public section we create our main functions that will handle the saving and loading. We can call them inside blueprint for convenience

UFUNCTION(BlueprintCallable, Category = SaveLoad)
bool SaveData();
UFUNCTION(BlueprintCallable, Category = SaveLoad)
bool LoadData();

Next, we in .CPP declare the functions. Remember to first include correct headers. This came with 4.16.  Also, we can define some value, so it is easier to reference it later on.

#include "Serialization/BufferArchive.h"
#include "Serialization/MemoryReader.h"
#include "Misc/FileHelper.h"
#define SAVEDATAFILENAME "SampleSave"

 

void AMyCharacter::SaveLoadData(FArchive& Ar, FVector& PlayerLocationToSaveOrLoad, FRotator& PlayerRotationToSaveOrLoad)
{
  //Save or load values
  Ar << PlayerLocationToSaveOrLoad;
  Ar << PlayerRotationToSaveOrLoad;
}

bool AMyCharacter::SaveData()
{
  // Data to Binary
  FBufferArchive ToBinary;
  SaveLoadData(ToBinary, PlayerLocation, PlayerRotation);

  // Are we successful?
  if (ToBinary.Num() <= 0) return false;

  //Save binaries to disk
  bool result = FFileHelper::SaveArrayToFile(ToBinary, TEXT(SAVEDATAFILENAME));

  //Empty the buffer's contents
  ToBinary.FlushCache();
  ToBinary.Empty();

  return result;
}

//Load Function
bool AMyCharacter::LoadData()
{
  TArray<uint8> BinaryArray;

  //load disk data to binary array
  if (!FFileHelper::LoadFileToArray(BinaryArray, TEXT(SAVEDATAFILENAME))) return false;

  if (BinaryArray.Num() <= 0) return false;

  //Memory reader is the archive that we're going to use in order to read the loaded data
  FMemoryReader FromBinary = FMemoryReader(BinaryArray, true);
  FromBinary.Seek(0);

  SaveLoadData(FromBinary, PlayerLocation, PlayerRotation);

  //Empty the buffer's contents
  FromBinary.FlushCache();
  BinaryArray.Empty();
  //Close the stream
  FromBinary.Close();

  return true;
}

In blueprint, we can save and load the rotation and set them to our player.

 

For custom classes, we need to override the << operator and allow to pass our new class.

friend FArchive& operator<<(FArchive& Ar, CustomClass& CustomClassRef);

Then declaration

FArchive& operator<<(FArchive& Ar, CustomClass& CustomClassRef)
{
  Ar << CustomClassRef.SomeValue;
  return Ar;
}

Rememer, overriding the << operator doesn’t remove the original! This means, you can create as many overrides as you wan’t with different parameters. It may be real time saver in some cases!

 

That’s it for reading and writing variables inside Actor in binary format!

 

 

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *