Consistent crashing on SaveGameToSlot

Unreal crashes consistently when UGameplayStatics::SaveGameToSlot() is called. It’s a mobile game. The idea is to load in all the highscore times on in the beginning of play session, and distribute them to arrays in the GameInstance (just testing with level 1 here), which then are displayed in the LevelSelect widget. Then save new time to disk any time neccessary. SaveSlotName, UserIndex and savegame object pointer is stored in GameInstance class.

void UMyGameInstance::SaveLevelTimeToDisk()
{
    if (SaveObject && LevelTimes.IsValidIndex(0))
    {
        SaveObject->time_L1 = LevelTimes[0];
        UGameplayStatics::SaveGameToSlot(SaveObject, SlotName, UserIndex);
    }
}

void UMyGameInstance::LoadLevelTimesFromDisk()
{
    if (bIsFreshSessionStart)
    {
        bIsFreshSessionStart = false;

        InitializeStatsArrays();

        if (UGameplayStatics::DoesSaveGameExist(SlotName, UserIndex))
        {
            SaveObject = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(SlotName, UserIndex));

            LevelTimes[0] = SaveObject->time_L1;

            BreakTime(LevelTimes[0], LevelTimesMinutes[0], LevelTimesSeconds[0], LevelTimesRemaining[0]);
        }

        else
        {
            SaveObject = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
        }
    }
}

I should mention. One time out of many many crashes now, a pop up window appeared with this message: “Pure virtual function being called while application was running (GIsRunning == 1).”

It only happened once.

I would appreciate any help on this as the whole project depends on getting this working.

I got it working now. Even though I don’t understand quite why, I must create a new savegame object, push everything into it, and then savetoslot, everytime I want to save. My thought was that I could have the same object around for the duration of the session, and only copy one time in before each save. That would reduce a lot of operations. If anyone knows how to accomplish that I would be happy to hear it.

1 Like

Thank you, i had the same issue. It was indeed the way to go, nicely done!
Small correction: You don’t have to recreate a new USaveGame each time, but you have to reload it each time you want to modify it.
In my case, i did a GetLibrary functions that does the following:

#define MYSAVELIB_SLOT FString("M_SAVE_LIB")

....

UMySaveLib* ULibrary::get_library()
{
	if (UGameplayStatics::DoesSaveGameExist(MYSAVELIB_SLOT, 0))
	{
		return Cast<UMySaveLib>(UGameplayStatics::LoadGameFromSlot(MYSAVELIB_SLOT, 0));
	}
	return nullptr;
}

void ULibrary::load_library()
{
	UMySaveLib* lib = get_library();
	if (!lib)
	{
		lib = Cast<UMySaveLib>(UGameplayStatics::CreateSaveGameObject(UMySaveLib::StaticClass()));
		lib->creation = FDateTime::Now().ToUnixTimestamp();
		save_library(lib);
	}
}

bool ULibrary::save_library(UMySaveLib* lib)
{
	if (lib == nullptr)
	{
		return false;
	}
	lib->modified = FDateTime::Now().ToUnixTimestamp();
	// and now overwriting
	return UGameplayStatics::SaveGameToSlot(lib, MYSAVELIB_SLOT, 0);
}

You have to call load_library at least once at object initialisation for instance. After that, you can access the UMySaveLib by calling get_library() and NOT store the pointer outiside of the function body.