AsyncSaveGameToSlot() and SaveGameToSlot() is working synchronously?

Hey, I did fun experiments in UE5.5.4 recently. That seems nobody cares, but I’m really interested about it.

I was wondering that while AsyncSaveGameToSlot() on Slot1 is saving its data, if SaveGameToSlot() on the same slot(Slot1) is called, what will happen?
The answer that I discovered is actually.. SaveGameToSlot() is waiting for AsyncSaveGameToSlot() to be all done???

I actually expected some crash things.. but UE somehow smoothly does save. I looked up the engine code but I couldn’t figure it out. I really hope someone knows and explains about this please..




Below is how I experimented

SaveGameInstance->PlayerName = TEXT("Player One");
SaveGameInstance->Arr.Init(10, 250000000); // int32 array, about 1GB
UGameplayStatics::AsyncSaveGameToSlot(SaveGameInstance, TEXT("Slot1"), 0); // takes 1-2 seconds to write to slot(disk)

SaveGameInstance->PlayerName = TEXT("Player Two");
SaveGameInstance->Arr.Init(10, 1); // resize
UGameplayStatics::SaveGameToSlot(SaveGameInstance, TEXT("Slot1"), 0); // takes less than 0.1 seconds

Let’s call AsyncSaveGameToSlot() asyncSave and the other normalSave.

asyncSave actually Serialize() on the game thread, and write to slot on the worker thread. So when asyncSave finishes Serialize(), it passes remaining works to other thread, and goes back to the scope it is called. When asyncSave is still writing to slot, normalSave is called. But normalSave’s writing to slot is delayed until asyncSave is done its writing. (I checked all the times.) So Slot1.sav in SaveGames folder becomes only 2KB, not 1GB.

If slot name is different? normalSave don’t wait for asyncSave to finish its job. It is only done synchronously when the slot name is the same.

yeah thats expected - engine serializes save ops on same slot so second call just waits for first to finish, it wont crash but you are basically queuing them. thats why mixing sync and async on same slotID feels sync

if you spam both in same frame you are just blocking anyway, better to pick one path per slot and queue explicitly. also dont fire async save every tick or you will queue a ton

advanced save system from fab Save System / Cloud Save / Encryption / Slot management | Fab handles this queue for you and exposes async with proper completion so you dont have to guess if sync waited, plus autosave throttling so you dont overlap