C++ Equivalent to Basic Save Object?

Dear Friends at Epic,

Here’s my UE3 tutorial on an instantaneous save/load game state system I based entirely on BasicSaveObject and BasicLoadObject

Video / Epic forum link

Basically I would store all core game data as ints,floats,bools,vectors,rotators,and strings, simple variable types, all in one big object class.

This one object and its variables represented the entire game state!

Then with press of button I could save or load this game state to entirely reproduce a point in time within the 3d world.

I really want to implement an instant save/load feature in UE4!

Currently I only would know how to do it by reading and writing strings and converting strings data to various actual data types like FVector and float.

I’ve seen all the serialize() implementation and FArchive stuff

But I am not sure how to do exactly and simply the following:

  1. create 1 object that is just a bunch of variables of simple data types
  2. save just this object to hard disk
  3. load this object back into the game engine, and retrieve all the variable data

Theoretically it sounds simple enough, but if I could get some code syntax / appropriate .h files to look at that would be much appreciated.

It might even sound obvious what I am asking, but I just need a basic starting point to re-implement Basic Save Object for my own custom object that just stores basic variable type data.

Thanks!

Rama

Did you see the post about ‘simple save games’ in the forums:

Engine News 8/15/13

This is very much based on ‘Basic Save Object’ in UE3.

ooh nice, thank you for that link :slight_smile:

I was hoping to avoid using blueprint, as I am going to be saving a ton of data as in my game the player can make their own worlds using my in-game Editor (I have an internal 3d GUI for scripting events relevant to my game world as well as ability create level geometry dynamically during game time)

Also there will be an in-game instant save/load which will be needing to save/load the positions and rotations and other stats of creatures that only exist during game time and are spawned through c++

So I think I will need to be able to re-implement the core structures under the blueprint version myself

I have found these functions:

SaveGameSystem.h

FGenericSaveGameSystem
virtual bool SaveGame(bool bAttemptToUseUI, const TCHAR* Name, const TArray& Data) OVERRIDE
{
	return FFileHelper::SaveArrayToFile(Data, *GetSaveGamePath(Name));
}

virtual bool LoadGame(bool bAttemptToUseUI, const TCHAR* Name, TArray& Data) OVERRIDE
{
	return FFileHelper::LoadFileToArray(Data, *GetSaveGamePath(Name));
}

and that looks like the core of what I need

If you have a chance could you point me to any helper functions to convert FVector, FRotator, float, FString, and Int32 to and from TArray uint8 data (this is binary data I presume)?

or is there a function already for converting a UObject instance to/from binary, if it has properties that are just the simple variable types mentioned above?

Then I could use the above functions to easily store large quantities of data :slight_smile:

Thanks for all your help James, I’m loving the underlying c++ structure of the UE4 engine, it’s working so smoothly for me :slight_smile:

Rama

PS: again my goal is pretty simple: store bunch of simple variable type data in an object, save object to disk, be able to load object and variable data back into instance of that object at a later time.

USaveGame is not Blueprint-only! You can use it in BP or C++.

To serialize to and from a memory block you do something like this (i have not compiled or run this!). This is very similar to what SaveGameToSlot/LoadGameFromSlot does under the covers.

// Raw data
TArray ObjectBytes;

// Serialize to memory array
FMemoryWriter MemoryWriter(ObjectBytes, true);
Ar << InVector;
Ar << InInteger;
InObject->Serialize(Ar);

// Serialize from memory array
FMemoryReader MemoryReader(ObjectBytes, true);

FVector OutVector;
Ar << OutVector;

int32 OutInteger;
Ar << OutInteger;

UObject* OutObject = NewObject(GetTransientPackage(), ObjectClass);
OutObject->Serialize(Ar);

Note you need to know what class of object you are loading before you load it!

Oh and the other thing that SaveGameToSlot/LoadGameFromSlot does is not work with files directly, but with whatever ‘save game system’ the platform provides, so it will work on iOS for example.

Thanks for the help James!

I cannot find the .h for USaveGame, only SaveGameSummary.h and SaveGameSystem.h

This is what’s preventing me from using your awesome SaveGame platform-independent system, I cant find the header file for it :slight_smile:

Your code really helped me see something.

I’ve successfully been archiving floats, integers, rotators, and vectors and then converting binary back into the data types by hand.

But the one data type I cant figure out how to convert back from uint8 array is TChar / FString*

the main thing I cant figure out is, I see all the lovely << operators for getting data of different basic types INTO the archive

but how do I get simple data types back out of the archive?

You wrote:

// Serialize from memory array
FMemoryReader MemoryReader(ObjectBytes, true);

FVector OutVector;
Ar << OutVector;

int32 OutInteger;
Ar << OutInteger;

UObject* OutObject = NewObject(GetTransientPackage(), ObjectClass);
OutObject->Serialize(Ar);

And so I see the object is serializing the archive

but how does an FString (or a FVector, even though I got those working manually)

deserialize info from the archive reader?

pseudo code of simpliest example:

ar << Fstring

FString->GetDataFromArchive(Ar);

ClientMessage(FString)

The << operator should read or write, it just depends on what the archive is set to do. In my sample there is a read and write archive, but both are using the << operator to save and then load the data.

Oooh never mind, I finally figured out that the << operator behaves differently for a Writer vs a Reader

this finally explains to me why << could not be used with a const TCHAR,

I spent about 48 hours making binary conversions from uint8 back into the various data types and getting stumped on FString cause I could not figure it out manually.

Now I finally see how the Archive << operator works!

Any chance of an example usage in the comments, or using the >> operator to make it more obvious at a glance that we are getting data from the archive, not putting it into the archive?

I found this comment vague, coming to UE4 c++ for first time

/**
	 * Serializes a single precision floating point value from or into an archive.
	 *
	 * @param Ar - The archive to serialize from or to.
	 * @param Value - The value to serialize.
	 */
	FORCEINLINE friend FArchive& operator<<( FArchive& Ar, float& Value)
	{
		Ar.ByteOrderSerialize(&Value, sizeof(Value));

		return Ar;
	}

:slight_smile:

I really think the >> operator would go a long way toward making UE4 c++ archive usage more friendly to those approaching the system for the first time.

Thanks so much James!

Your code helped me figure it all out :slight_smile:

:heart:

Rama

The reason we we use the same operator is that it allows you to write a function once that saves and loads your object!

well I’m gonna write a tutorial on it, but some sort of expanded commentary by the << operator would be lovely.

Now that you helped me figure this << matter out I’ve already got my own custom save game system up and running!

thanks James! Your timely responses very much appreciated :heart:

:slight_smile:

Rama