I’ve released a beta version of my game and users are complaining about save games being deleted. This is really confusing because I have never been able to reproduce the issue locally, save games for me always worked. I am not doing anything special. I init, load, and write my save game with the following code:
void ULlamagotchiGameInstance::InitSaveGame_Implementation()
{
if (SaveInstance == nullptr)
{
if (!LoadSaveGame())
{
SaveInstance = CreateSaveGame();
ensure(SaveInstance != nullptr);
SaveInstance->bIsFirstLaunchInLevel = true; // Game launching for the first time
}
}
}
bool ULlamagotchiGameInstance::LoadSaveGame()
{
SaveInstance = Cast<ULGSaveGame>(UGameplayStatics::LoadGameFromSlot(kGameSlotName, 0));
return SaveInstance != nullptr;
}
bool ULlamagotchiGameInstance::WriteSaveGameToDisk(APetCharacter* Pet, ALlamagotchiPlayerController* PlayerController, APawn* PlayerPawn)
{
if (!UpdateSaveInMemory(Pet, PlayerController, PlayerPawn))
{
UE_LOG(LogLgGameInstance, Log, TEXT("Savegame write to memory failed"));
return false;
}
// Save game
if(UGameplayStatics::SaveGameToSlot(SaveInstance, kGameSlotName, 0))
{
UE_LOG(LogLgGameInstance, Log, TEXT("Savegame successfully saved to disk"));
return true;
}
UE_LOG(LogLgGameInstance, Error, TEXT("Savegame write to disk failed"));
return false;
}
bool ULlamagotchiGameInstance::UpdateSaveInMemory(APetCharacter* Pet, ALlamagotchiPlayerController* PlayerController,
APawn* PlayerPawn)
{
UE_LOG(LogLgGameInstance, Log, TEXT("Updating save game in memory"));
if (!SaveInstance)
{
UE_LOG(LogLgGameInstance, Error, TEXT("SaveInstance was null when trying to update save in memory"));
return false;
}
[snip]
TArray<AActor*> SaveableActors;
UGameplayStatics::GetAllActorsWithInterface(GetWorld(), USaveableInterface::StaticClass(), SaveableActors);
for (auto SaveableActor : SaveableActors)
{
SaveInstance->ActorSaver(SaveableActor, SaveInstance->CurrentLevel);
}
[snip]
UE_LOG(LogLgGameInstance, Log, TEXT("Updated save game in memory"));
return true;
}
The only thing I can think of that is a little bit non-standard is I am using a FObjectAndNameAsStringProxyArchive to write my actor data:
/**
* Save Game Archiver.
*/
struct FLGSaveGameArchive : public FObjectAndNameAsStringProxyArchive
{
FLGSaveGameArchive(FArchive& InInnerArchive)
: FObjectAndNameAsStringProxyArchive(InInnerArchive,true)
{
ArIsSaveGame = true;
}
};
void ULGSaveGame::ActorSaver(AActor* SaveActor, ELgLevel Level)
{
// All actors passed here need to implement this interface
ISaveableInterface* ImplementsInterface = Cast<ISaveableInterface>(SaveActor);
check(ImplementsInterface != nullptr);
FString UniqueId = FObjectRecord::GenerateUniqueId(SaveActor, Level);
FObjectRecord& ObjectRecord = UniqueIdToObjectRecords.Emplace(UniqueId);
ObjectRecord.UniqueId = UniqueId;
ObjectRecord.Name = SaveActor->GetFName();
ObjectRecord.Transform = SaveActor->GetTransform();
ObjectRecord.Class = SaveActor->GetClass();
ObjectRecord.bShouldSpawn = ISaveableInterface::Execute_GetShouldSpawn(SaveActor);
ObjectRecord.LevelToSpawnIn = ISaveableInterface::Execute_GetLevelToSpawnIn(SaveActor);
SaveData(SaveActor, ObjectRecord.Data);
UE_LOG(LogSaveGame, Display, TEXT("Complete Save Actor %s"), *SaveActor->GetName())
}
void ULGSaveGame::SaveData(UObject* Object, TArray<uint8_t>& Data)
{
if (Object == nullptr) return;
FMemoryWriter MemoryWriter = FMemoryWriter(Data, true);
FLGSaveGameArchive MyArchive(MemoryWriter);
Object->Serialize(MyArchive);
}
If anybody has any suggestions or can offer any tips it would be greatly appreciated. Really scratching my head on this one since I haven’t been able to reproduce locally.