Problem loading variables from save game to game instance at game start in c++

I have spent hours rewriting my code into all sorts of different shapes and sizes but I can’t figure out how to save an array of booleans in c++. I have just followed the “Saving and Loading Your Game” documentation as closely as possible and am still obtaining the same results.

I am testing the hair boolean array as the default value generated from the savegame is 0 but its default value should be 13. A total of 14 elements in the array.

With no SaveGame.sav present the game will generate one and the values are correct as indicated by the logs.


 

  1. LogTemp: Warning: Game Saved from GameSave
  1. LogTemp: Warning: GAME SAVED FROM GAME INSTANCE. local Hair bool array lenghth was 14. savegame value is 14
  1. LogTemp: Warning: GAME SAVE CREATED FROM GAMEMODE
  1. LogTemp: Warning: GAME MODE BEGIN PLAY CALLED. Hair bool Array length is 14

 

When the game is next started it finds that there is a SaveGame and apparently loads it but the effects of this can not be seen or logged.


 

  1. LogTemp: Warning: GAME LOADED FROM GAME INSTANCE! Lenght of hair bool array is 0
  1. LogTemp: Warning: GAME LOADED FROM GAMEMODE
  1. LogTemp: Warning: GAME MODE BEGIN PLAY CALLED. Hair bool Array length is 0

 

If I run the ClearSaveGame() function the logs produced by the next SaveGame() are the same as if there was no SaveGame.sav present at launch, however this is not remembered.

I’m assuming that I am not loading the data correctly and I am just running around in circles at this stage… Thank you in advance for any help!

Below are the problem c++ files, I have tried writing it as simple as possible.

DDMenuGameMode.cpp


 

  1. #include "Kismet/GameplayStatics.h"
  1. #include "System/DDGameInstance.h"
  1. #include "System/DDSaveGame.h"
  1. void ADDMenuGameMode::BeginPlay()
  1. {
  1. // Get reference to custom game instance and run load game function
  1. GameInstanceRef = Cast<UDDGameInstance>(GetGameInstance());
  1. SaveGameRef = Cast<UDDSaveGame>(UGameplayStatics::CreateSaveGameObject(UDDSaveGame::StaticClass()));
  1. if (SaveGameRef && GameInstanceRef)
  1. {
  1. LoadGame();
  1. }
  1. else{UE_LOG(LogTemp, Error, TEXT("SAVE GAME NOT CREATED AT BEGIN PLAY ON GAME MODE, COULD NOT SET TO GAME INSTANCE!!!")); return;}
  1. UE_LOG(LogTemp, Warning, TEXT("GAME MODE BEGIN PLAY CALLED. Hair bool Array length is %i"), GameInstanceRef->GetHasHair().Num());
  1. SpawnMenuObjects();
  1. MenuController->BeginIntro();
  1. }
  1. void ADDMenuGameMode::LoadGame()
  1. {
  1. if(UGameplayStatics::DoesSaveGameExist(TEXT("SaveGame"), 0))
  1. {
  1. GameInstanceRef->LoadGame();
  1. UE_LOG(LogTemp, Warning, TEXT("GAME LOADED FROM GAMEMODE"));
  1. }
  1. else
  1. {
  1. GameInstanceRef->SaveGame();
  1. UE_LOG(LogTemp, Warning, TEXT("GAME SAVE CREATED FROM GAMEMODE"));
  1. }
  1. }

 

DDGameInstance.cpp


 

  1. #include "System/DDSaveGame.h"
  1. #include "Kismet/GameplayStatics.h"
  1. void UDDGameInstance::SaveGame()
  1. {
  1. UDDSaveGame* SaveGameRef = Cast<UDDSaveGame>(UGameplayStatics::CreateSaveGameObject(UDDSaveGame::StaticClass()));
  1. if(SaveGameRef)
  1. {
  1. SaveGameRef->FullSave(bHasChest, bHasLegs, bHasFace, bHasHands, bHasHair, bHasBeard, bHasEyebrows, bMaleCharacter, CurrentCoins, SelectedChest, SelectedLegs, SelectedFace, SelectedHands, SelectedHair, SelectedBeard, SelectedEyebrows, SelectedMenuMusic, SelectedGameMusic);
  1. UGameplayStatics::SaveGameToSlot(SaveGameRef, TEXT("SaveGame"), 0);
  1. UE_LOG(LogTemp, Warning, TEXT("GAME SAVED FROM GAME INSTANCE. local Hair bool array lenghth was %i. savegame value is %i"), bHasHair.Num(), SaveGameRef->LenghtOfHairArray());
  1. }
  1. else{UE_LOG(LogTemp, Error, TEXT("SAVE GAME IS NULL"));}
  1. }
  1. void UDDGameInstance::LoadGame()
  1. {
  1. if (UDDSaveGame* LoadedGame = Cast<UDDSaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("SaveGame"), 0)))
  1. {
  1. // The operation was successful, so LoadedGame now contains the data we saved earlier.
  1. LoadedGame->LoadGame(bHasChest, bHasLegs, bHasFace, bHasHands, bHasHair, bHasBeard, bHasEyebrows, bMaleCharacter, CurrentCoins, SelectedChest, SelectedLegs, SelectedFace, SelectedHands, SelectedHair, SelectedBeard, SelectedEyebrows, SelectedGameMusic, SelectedMenuMusic);
  1. UE_LOG(LogTemp, Warning, TEXT("GAME LOADED FROM GAME INSTANCE! Lenght of hair bool array is %i"), bHasHair.Num());
  1. }
  1. }
  1. void UDDGameInstance::ClearSaveGame()
  1. {
  1. UDDSaveGame* SaveGameRef = Cast<UDDSaveGame>(UGameplayStatics::CreateSaveGameObject(UDDSaveGame::StaticClass()));
  1. if(SaveGameRef)
  1. {
  1. bHasChest = {true, false, false, false, false, false, false, true, false, false, false, false};
  1. bHasLegs = {true, false, false, false, false, false, false, true, false, false, false, false};
  1. bHasFace = {true, true, true, false, false, true, true, true, false, false};
  1. bHasHands = {true, false, false, true, false};
  1. bHasHair = {false, false, false, false, false, false, false, false, false, false, false, false, false, true};
  1. bHasBeard = {false, false, false, false, true};
  1. bHasEyebrows = {false, false, false, false, false, false, false, true};
  1. bMaleCharacter = true;
  1. bIndestructibleCheat = false;
  1. CurrentCoins = 0;
  1. SelectedChest = 0;
  1. SelectedLegs = 0;
  1. SelectedFace = 0;
  1. SelectedHands = 0;
  1. SelectedHair = 13;
  1. SelectedBeard = 4;
  1. SelectedEyebrows = 7;
  1. SelectedGameMusic = 3;
  1. SelectedMenuMusic = 0;
  1. SaveGameRef->FullSave(bHasChest, bHasLegs, bHasFace, bHasHands, bHasHair, bHasBeard, bHasEyebrows, bMaleCharacter, CurrentCoins, SelectedChest, SelectedLegs, SelectedFace, SelectedHands, SelectedHair, SelectedBeard, SelectedEyebrows, SelectedMenuMusic, SelectedGameMusic);
  1. UGameplayStatics::SaveGameToSlot(SaveGameRef, TEXT("SaveGame"), 0);
  1. }
  1. else{UE_LOG(LogTemp, Error, TEXT("SAVEGAMEREF MISSING"));}
  1. }

 

DDSaveGame.h


 

  1. #pragma once
  1. #include "CoreMinimal.h"
  1. #include "GameFramework/SaveGame.h"
  1. #include "DDSaveGame.generated.h"
  1. /**
  1. *
  1. */
  1. UCLASS()
  1. class DESERTDASH_API UDDSaveGame : public USaveGame
  1. {
  1. GENERATED_BODY()
  1. public:
  1. void FullSave(TArray<bool> Chests, TArray<bool> Legs, TArray<bool> Faces, TArray<bool> Hands, TArray<bool> Hairs, TArray<bool> Beards, TArray<bool> Eyebrows, bool MaleCharacter, int Coins, int Chest, int Leg, int Face, int Hand, int Hair, int Beard, int Eyebrow, int GameMusic, int MenuMusic);
  1. void CoinSave(int Coins);
  1. void LoadGame(TArray<bool>& ChestsOUT, TArray<bool>& LegsOUT, TArray<bool>& FacesOUT, TArray<bool>& HandsOUT, TArray<bool>& HairsOUT, TArray<bool>& BeardsOUT, TArray<bool>& EyebrowsOUT, bool& MaleCharacterOUT, int& CoinsOUT, int& ChestOUT, int& LegOUT, int& FaceOUT, int& HandOUT, int& HairOUT, int& BeardOUT, int& EyebrowOUT, int& GameMusicOUT, int& MenuMusicOUT);
  1. int LenghtOfHairArray();
  1. private:
  1. TArray<bool> SavedChests;
  1. TArray<bool> SavedLegs;
  1. TArray<bool> SavedFaces;
  1. TArray<bool> SavedHands;
  1. TArray<bool> SavedHairs;
  1. TArray<bool> SavedBeards;
  1. TArray<bool> SavedEyebrows;
  1. bool bSaveMaleCharacter;
  1. int CurrentCoins;
  1. int SelectedChest;
  1. int SelectedLegs;
  1. int SelectedFace;
  1. int SelectedHands;
  1. int SelectedHair;
  1. int SelectedBeard;
  1. int SelectedEyebrows;
  1. int SelectedGameMusic;
  1. int SelectedMenuMusic;
  1. };

 

DDSaveGame.cpp


 

  1. #include "System/DDSaveGame.h"
  1. void UDDSaveGame::FullSave(TArray<bool> Chests, TArray<bool> Legs, TArray<bool> Faces, TArray<bool> Hands, TArray<bool> Hairs, TArray<bool> Beards, TArray<bool> Eyebrows, bool MaleCharacter, int Coins, int Chest, int Leg, int Face, int Hand, int Hair, int Beard, int Eyebrow, int GameMusic, int MenuMusic)
  1. {
  1. SavedChests = Chests;
  1. SavedLegs = Legs;
  1. SavedFaces = Faces;
  1. SavedHands = Hands;
  1. SavedHairs = Hairs;
  1. SavedBeards = Beards;
  1. SavedEyebrows = Eyebrows;
  1. bSaveMaleCharacter = MaleCharacter;
  1. CurrentCoins = Coins;
  1. SelectedChest = Chest;
  1. SelectedLegs = Leg;
  1. SelectedFace = Face;
  1. SelectedHands = Hand;
  1. SelectedHair = Hair;
  1. SelectedBeard = Beard;
  1. SelectedEyebrows = Eyebrow;
  1. SelectedGameMusic = GameMusic;
  1. SelectedMenuMusic = MenuMusic;
  1. UE_LOG(LogTemp, Warning, TEXT("Game Saved from GameSave"));
  1. }
  1. void UDDSaveGame::CoinSave(int Coins)
  1. {
  1. CurrentCoins = Coins;
  1. }
  1. void UDDSaveGame::LoadGame(TArray<bool>& ChestsOUT, TArray<bool>& LegsOUT, TArray<bool>& FacesOUT, TArray<bool>& HandsOUT, TArray<bool>& HairsOUT, TArray<bool>& BeardsOUT, TArray<bool>& EyebrowsOUT, bool& MaleCharacterOUT, int& CoinsOUT, int& ChestOUT, int& LegOUT, int& FaceOUT, int& HandOUT, int& HairOUT, int& BeardOUT, int& EyebrowOUT, int& GameMusicOUT, int& MenuMusicOUT)
  1. {
  1. ChestsOUT = SavedChests;
  1. LegsOUT = SavedLegs;
  1. FacesOUT = SavedFaces;
  1. HandsOUT = SavedHands;
  1. HairsOUT = SavedHairs;
  1. BeardsOUT = SavedBeards;
  1. EyebrowsOUT = SavedEyebrows;
  1. MaleCharacterOUT = bSaveMaleCharacter;
  1. CoinsOUT = CurrentCoins;
  1. ChestOUT = SelectedChest;
  1. LegOUT = SelectedLegs;
  1. FaceOUT = SelectedFace;
  1. HandOUT = SelectedHands;
  1. HairOUT = SelectedHair;
  1. BeardOUT = SelectedBeard;
  1. EyebrowOUT = SelectedEyebrows;
  1. GameMusicOUT = SelectedGameMusic;
  1. MenuMusicOUT = SelectedMenuMusic;
  1. }
  1. int UDDSaveGame::LenghtOfHairArray()
  1. {
  1. return SavedHairs.Num();
  1. }

 

I have also posted this in the Answer Hub but it has been 18 hours and is still waiting approval by a moderator.

Thanks again for any help! I hate having to ask but I am getting absolutely nowhere on my own! Also, sorry about the lack of continuity between naming of my variables, so much has been altered from how I originally wrote it to try getting things working and to make sure I wasn’t confusing myself along the way.

Bump.

My question on the answer hub still is waiting for moderator approval… I really need assistance with this issue, I know its something I’m doing wrong but I just can’t figure it out!

use add(); when adding to a TArray and remove when removing
Example



SavedChests.Add(Chests);

Thank you so much! I am going to do this now and I will post my results :slight_smile:

In the array.h file. It has everything you need to use with TArrays, You must read it, go check it out. So many things to work with.

I am still getting the same results after multiple ways of handling my arrays differently.



//header
void UpdateArray(TArray<bool>& ArrayToUpdate, TArray<bool> NewValues)

//implementation
{
    ArrayToUpdate.Empty();
    for(int i = 0; i < NewValues.Num() - 1; i++)
    {
        ArrayToUpdate.Add(NewValues*);
        UE_LOG(LogTemp, Warning, TEXT("Value is %s at %i"), ArrayToUpdate* ? TEXT("true") : TEXT("false"), i);
    }
    UE_LOG(LogTemp, Warning, TEXT("New Array length is %i"), ArrayToUpdate.Num());
}


I now think it is an issue with how I am loading the game. The code below are changes I have made to my original code to handle using the UpdateArray function (I really need to remove those logs, so much spam but it all looks like it works until I load the data)

DDGameInstance.h



void UDDGameInstance::LoadGame()
{
    UDDSaveGame* LoadedGame = Cast<UDDSaveGame>(UGameplayStatics::CreateSaveGameObject(UDDSaveGame::StaticClass()));
    if (LoadedGame = Cast<UDDSaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("SaveGame"), 0)))
    {
        TArray<bool> TempChest, TempLegs, TempFace, TempHands, TempHair, TempBeard, TempEyebrows;
        // The operation was successful, so LoadedGame now contains the data we saved earlier.
        LoadedGame->LoadGame(TempChest, TempLegs, TempFace, TempHands, TempHair, TempBeard, TempEyebrows, bMaleCharacter, CurrentCoins, SelectedChest, SelectedLegs, SelectedFace, SelectedHands, SelectedHair, SelectedBeard, SelectedEyebrows, SelectedGameMusic, SelectedMenuMusic);
        UpdateArray(bHasChest, TempChest);
        UpdateArray(bHasLegs, TempLegs);
        UpdateArray(bHasFace, TempFace);
        UpdateArray(bHasHands, TempHands);
        UpdateArray(bHasHair, TempHair);
        UpdateArray(bHasBeard, TempBeard);
        UpdateArray(bHasEyebrows, TempEyebrows);
        UE_LOG(LogTemp, Warning, TEXT("GAME LOADED FROM GAME INSTANCE! Lenght of hair bool array is %i"), bHasHair.Num());
    }
}


DDSaveGame.cpp



void UDDSaveGame::FullSave(TArray<bool> Chests, TArray<bool> Legs, TArray<bool> Faces, TArray<bool> Hands, TArray<bool> Hairs, TArray<bool> Beards, TArray<bool> Eyebrows, bool MaleCharacter, int Coins, int Chest, int Leg, int Face, int Hand, int Hair, int Beard, int Eyebrow, int GameMusic, int MenuMusic)
{
    UpdateArray(SavedChests, Chests);
    UpdateArray(SavedLegs, Legs);
    UpdateArray(SavedFaces, Faces);
    UpdateArray(SavedHands, Hands);
    UpdateArray(SavedHairs, Hairs);
    UpdateArray(SavedBeards, Beards);
    UpdateArray(SavedEyebrows, Eyebrows);
    bSaveMaleCharacter = MaleCharacter;
    CurrentCoins = Coins;
    SelectedChest = Chest;
    SelectedLegs = Leg;
    SelectedFace = Face;
    SelectedHands = Hand;
    SelectedHair = Hair;
    SelectedBeard = Beard;
    SelectedEyebrows = Eyebrow;
    SelectedGameMusic = GameMusic;
    SelectedMenuMusic = MenuMusic;
    UE_LOG(LogTemp, Warning, TEXT("Game Saved from GameSave"));
}

void UDDSaveGame::LoadGame(TArray<bool>& ChestsOUT, TArray<bool>& LegsOUT, TArray<bool>& FacesOUT, TArray<bool>& HandsOUT, TArray<bool>& HairsOUT, TArray<bool>& BeardsOUT, TArray<bool>& EyebrowsOUT, bool& MaleCharacterOUT, int& CoinsOUT, int& ChestOUT, int& LegOUT, int& FaceOUT, int& HandOUT, int& HairOUT, int& BeardOUT, int& EyebrowOUT, int& GameMusicOUT, int& MenuMusicOUT)
{
    UpdateArray(ChestsOUT, SavedChests);
    UpdateArray(LegsOUT, SavedLegs);
    UpdateArray(FacesOUT, SavedFaces);
    UpdateArray(HandsOUT, SavedHands);
    UpdateArray(HairsOUT, SavedHairs);
    UpdateArray(BeardsOUT, SavedBeards);
    UpdateArray(EyebrowsOUT, SavedEyebrows);
    MaleCharacterOUT = bSaveMaleCharacter;
    CoinsOUT = CurrentCoins;
    ChestOUT = SelectedChest;
    LegOUT = SelectedLegs;
    FaceOUT = SelectedFace;
    HandOUT = SelectedHands;
    HairOUT = SelectedHair;
    BeardOUT = SelectedBeard;
    EyebrowOUT = SelectedEyebrows;
    GameMusicOUT = SelectedGameMusic;
    MenuMusicOUT = SelectedMenuMusic;
    UE_LOG(LogTemp, Warning, TEXT("GameMusic Value is %i and should be 3"), SelectedGameMusic);
}


I definitely am not saving/loading the game correctly since GameMusic is defaulting to 0 or whatever I have the defaults set to in DDSaveGame…

I decided to make the most of my time while waiting for help and am now using AsyncLoadGameFromSlot and AsyncSaveGameToSlot with the same results. I thought I could have been doing too much for the synchronous versions. At least I should be able to do that now, once I get the whole saving and loading thing working in general…

your ints



int CurrentCoins;

should be int32 CurrentCoins;

Thanks for that, I’ve changed any usage of int to int32 and am still having the same issue.

Bump. I still haven’t figured out why my code isn’t working.

this line will cause you problems




TArray<bool> TempChest, TempLegs, TempFace, TempHands, TempHair, TempBeard, TempEyebrows;


Make them seperate then they will each get the bool in the TArray.

These will work
EXAMPLE:



TArray<bool> TempChest;
TArray<bool> TempLegs;
TArray<bool> TempFace;
TArray<bool> TempHands;
TArray<bool> TempHair;
TArray<bool> TempBeard;
TArray<bool> TempEyebrows;


Rest looks like it should work, once you fix the defines.

Thanks again for going through my code and troubleshooting it for me, I appreciate your help so much!

I have just gone through and changed my code to your recommendations and am still having the same issue.

I have also just tested what the SaveGameToSlot() function is returning as recommended in a comment to this problem on the answer hub, it is returning true as expected.

I got very excited when I found that I missed the Super::BeginPlay() for that override in DDMenuGameMode.cpp but this also had no results.

Aren’t you missing the UPROPERTY() macro before each property declaration? The reflection system will not recognize any variable not “marked” with this macro.

1 Like

Yes I am! Thank you so much! I literally just figured this out and answered my questions on the answer hub and forgot to check here.

This solved the issue! Thanks so much for that!