I’m looking for a way to allow the player to have multiple save slots, and load whichever one they choose. I see that I can save a game to a slot with a specific name, and check if there is a slot with a specific name, but I’m not seeing how to get all of the save slots. Does something like this already exist, or am I looking at adding C++ code to inspect the directory?
you could name all of your save files the same way, like “save01”, “save02”… “save10” then have a for loop that searches through all of those using a DoesSaveGameExist node.
that would give you a list of available save files, but you would have to load each file to get any meta data out of it, like player name, progress tokens, play time, death count, character stats, etc… and that might be slow to populate that list, because each save file could have thousands of extra pieces of data that have nothing to do with the info needed to render the menu cards. to speed things up, you might need to make a smaller “meta save file” that holds just the menu data for the regular save files.
so if you save to slot 5, it will write to Save05 and Meta05. then when you go to the load game screen, it loops through each MetaXX file, using DoesSaveGameExist, and if it does, LoadGameFromSlot, then copy that data to a structure that you use to hold the menu data, then it moves on to the next Meta file until it reaches the max for that page (lets say 10). the only time you need to load any of the SaveXX files, is when the player chooses a file from the menu.
if you want to search a directory in c++, these might help:
objectLibrary, FAssetRegistry, FAssetDataGatherer
Adding to what ScottSpadea said,
A better way would be to create a single Meta file, which has an array of information which contain following info at each element:
- Save Game Slot Name (string)
- User Index (Integer)
- Date Created (Date and Time)
- Player Name (string)
So you just need to load this single meta file and iterate over the array with a for-each-element loop to create Load Game List of Saved Games Slots.
This will be flexible and no need of C++.
Looks like you guys know a lot about saving. Hopefully you help with a question. Saving spawned hierarchical instanced meshes to a save file. The save files can be 200 or 300 megs. I looked in the save files and for the 50,000 instanced meshes it is saving the long name for each one, like the following:
\Gamedirectory\Name of the files\name of the Blue Print\ Name of the Instanced
Its actually longer than that but it seems like a waste considering they are all the exact same name.
Maybe saving this wrong, There is a loop in the blueprint that copies the index, transform and item of the instanced meshes to a game save file.
Do you know if this is normal?
Thank you,
John
@Deamonpog, this would be nice if you have a small and a non-variable length slot like a max of 10 saves but if the save slots are variable in number then you are risking a filled memory buffer issue
What does this have to do with the OP question?
This seems like a very elegant solution, I would be much more inclined to use this method than to have “predictable” slot names.
I would do a different approach.
Create some own save game class in which you save all save game slot names.
Save this under a special slot name for example “slot names” and load only this when you load up your save game list.
After the player has select the slot and wants to play, you load the correct selected slot.
I think this can solve your issue in bp
Those nodes are in a build-in plugin called Blueprint File Utilities
This seems to be the best way to do it.
This should be marked as the solution; it’s also really easy to convert to C++
const FString& SaveDir = UKismetSystemLibrary::GetProjectSavedDirectory() / "SaveGames";
TArray<FString> FoundFiles;
const FString& ext = ".sav";
IFileManager::Get().FindFiles(FoundFiles, *SaveDir, *ext);
TArray<FString> FileNames;
if (FoundFiles.Num() > 0)
{
for (const FString& F : FoundFiles)
{
// Removes the file extension
FileNames.AddUnique(F.LeftChop(4));
}
}
if (FileNames.Num() > 0)
{
for (const FString& F : FileNames)
{
// Do what you want now with the slot name
}
}