Having trouble loading anything from a TMultiMap being stored in a SaveGame. The MultiMap uses EGameModeActorName as keys and FPlayerScores as values.
SaveGame headerfile:
// Player Score data storage object
UPROPERTY(VisibleAnywhere, Category = "Scoring")
FPlayerScore PlayerScores;
// Map to store all scores
TMultiMap<EGameModeActorName, FPlayerScore> PlayerScoreMap;
// Add the Player Scores to the map of Player Scores
UFUNCTION(BlueprintCallable, Category = "Scoring")
void SavePlayerScores(EGameModeActorName GameModeActorName, FPlayerScore PlayerScoreStructToAdd);
The loading and saving is done inside AGameModeActorBase. Saving doesn’t necessarily seem to be a problem since when I look at both PlayerScores and PlayerScoreMap, they are both non-empty. However, when I load the SaveGamePlayerScore, PlayerScoreMap is always empty, but PlayerScores is not, which leads me to believe there’s something wrong with PlayerScoreMap.
Since I’m using a UENUM (EGameModeActorName) as keys inside the MultiMap, do I need to set up custom SetAllocator and KeyFuncs? What’s going wrong here?
Edit: It looks like this might be because I can’t use the UPROPERTY() specifier to TMultiMap?
That’s correct. Savegame serialization can only automatically handle the things that are exposed to reflection and the UPROPERTY macro is how things are exposed to reflection. Since TMultiMap isn’t supported by the UPROPERTY macro you won’t be able to get automatic serialization of that member.
Your two options are: 1) Store it in a multi-map someplace else for runtime accesses and convert it to an array or some other data set when writing data to your save. 2) Modify your data structure to be compatible with UPROPERTY. In this case that probably means a) using TMap, b) the value being a custom structure, c) which contains an array of FPlayerScores. Or something else, but that’s more or less all a multi-map is anyway.
Late reply, but I ended up going with the second option you suggested. I just made another USTRUCT with its only member being a TArray of FPlayerScores, so the final signature looks like
I’m actually using structs for both the key and value of the TMap now. To do this, I overrode the == operator like so (this goes inside the struct that I’m using as the key, which is FGameModeActorStruct)
I use this to store player scores based on which game mode and song are selected. Here’s an example of me saving scores to an instance of FPlayerScores at the end of a game mode:
// iterate through all elements in PlayerScoreMap
for (TTuple<FGameModeActorStruct, FPlayerScoreArrayWrapper>& Elem : PlayerScoreMap)
{
// get array of player scores from current key value
TArray<FPlayerScore> TempArray = Elem.Value.PlayerScoreArray;
float HighScore = 0.f;
// iterate through array of player scores to find high score for game mode & song
for (FPlayerScore& PlayerScoreObject : TempArray)
{
if (PlayerScoreObject.HighScore > HighScore)
{
HighScore = PlayerScoreObject.HighScore;
}
}
}