Saving Data To File

Hi all, I am working on a save game system, all I need is an Array storing information about unlocked levels and later I will need to store the settings as well.

I followed the Save System example by Rama:

A new, community-hosted Unreal Engine Wiki - Announcements - Unreal Engine Forums,Read%26_Write_Any_Data_to_Compressed_Binary_Files

It all seemed to work fine.
However when I tried to save multiple times I started getting crashes on Load, first I searched for errors in the code and tried many many things, so then I noticed something weird is happening with the save file.

I think I’m having problems with saving FBufferArchive correctly, it looks like the FBufferArchive doesn’t get cleared , so each time I save, the data is added again, and after a few saves gets messed up and then the data can’t be loaded anymore and game crashes.

I made some tests, the variables are ok, I also tried to delete the file each time before the save,
but same thing happens which suggests the data builds up in the buffer and doesn’t get cleared after save.

Following the example I also noticed GFileManager->TheFunction() does not exist anymore so for managing files I used:

`FPlatformFileManager::Get().GetPlatformFile().TheFunction();

Now here is the code, first the .h file with variables I’m saving:

        UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = JumpyFrogs)
	TArray <bool> UnlockedArray;
	
	int32 NumGemsCollected;
	FVector PlayerLocation;
	TArray<FRotator> ArrayOfRotationsOfTheStars;
	FBufferArchive ToBinary;

And the Save function which is causing these issues:

bool AJumpyFrogsGameMode::SaveGameDataToFile(const FString& FullFilePath, FBufferArchive& ToBinary)
{
	SaveLoadData(ToBinary, NumGemsCollected, PlayerLocation, ArrayOfRotationsOfTheStars, UnlockedArray);

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

	// Binary to Hard Disk
	if (FFileHelper::SaveArrayToFile(ToBinary, *FullFilePath))
	{
		// Free Binary Array 		
		ToBinary.FlushCache();
		ToBinary.Empty();
		ToBinary.Close();
		GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Green, TEXT("Save Success!"));
		return true;
	}

	// Free Binary Array 	
	ToBinary.FlushCache();
	ToBinary.Empty();
	ToBinary.Close();
	GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Red, TEXT("File Could Not Be Saved!"));

	return false;
}

And here is how the save file looks after saving:

First Save:

2b00 0000 0000 e043 0000 2844 0000 4843
0100 0000 0000 e043 0000 2844 0000 4843
2100 0000 0101 0101 0101 0101 0101 0101
0101 0101 0101 0101 0101 0101 0101 0101
0101 0101 01

Second Save:

cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd 2b00 0000 0000 e043 0000
2844 0000 4843 0100 0000 0000 e043 0000
2844 0000 4843 2300 0000 0100 0001 0101
0101 0101 0101 0101 0101 0101 0101 0101
0101 0101 0101 0101 0101 0101 01

Third Save:

cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cd2b 0000
0000 00e0 4300 0028 4400 0048 4301 0000
0000 00e0 4300 0028 4400 0048 4324 0000
0001 0000 0001 0101 0101 0101 0101 0101
0101 0101 0101 0101 0101 0101 0101 0101
0101 0101 01

Fourth Save:

cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cdcd cdcd cdcd cdcd cdcd cdcd
cdcd cdcd cd2b 0000 0000 00e0 4300 0028
4400 0048 4301 0000 0000 00e0 4300 0028
4400 0048 4325 0000 0001 0000 0000 0101
0101 0101 0101 0101 0101 0101 0101 0101
0101 0101 0101 0101 0101 0101 0101 

Fifth Save:

ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ+NULNULNULNULNULàCNULNUL(NULNULNULNULNULNUL and a bunch of SOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOHSOH

So yeah now I’m not sure what to try next, I also tried ToBinary.Flush(); didn’t help…

First, I wouldn’t make the FBufferArchive a class member. Second, .Num() will never return less than 0. FlushCache and Close do nothing on that class. Here’s how I’d rewrite this code:

bool AJumpyFrogsGameMode::SaveGameDataToFile(const FString& FullFilePath)
 {
     FBufferArchive ToBinary;
     SaveLoadData(ToBinary, NumGemsCollected, PlayerLocation, ArrayOfRotationsOfTheStars, UnlockedArray);

     bool bSucceeded = false; 
     if (ToBinary.Num() > 0)
     {
          bSucceeded = FFileHelper::SaveArrayToFile(ToBinary, *FullFilePath);
          GEngine->AddOnScreenDebugMessage(-1, 2.f,
               bSucceeded ? FColor::Green : FColor::Red,
               bSucceeded ? TEXT("Save Success!") : TEXT("File Could Not Be Saved!"));
    }
 
     return bSucceeded;
 }

Hi :), yes you are correct, this was the problem, and I also had FBufferArchive ToBinary; as a global variable , bad idea!
Well that was fun :D, another lesson learned, thanks a lot for the quick help!

Here’s the tested UE 4.10.1 version, save/load part of my code for anyone else reading this, it should work just the same for Compressing data, like in the example by Rama (needs a few updates)!

I’m experiencing some problems pasting the code in here so I’m just adding a text file ! link text

Although it was a problem long time ago, I hadn’t found a solution anywhere. So I write it here.

Call ToBinary.Seek(0) to reset Offset. ToBinary.Flush() did nothing.