Can't load bool array for 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.

LogTemp: Warning: Game Saved from GameSave
LogTemp: Warning: GAME SAVED FROM GAME INSTANCE. local Hair bool array lenghth was 14. savegame value is 14
LogTemp: Warning: GAME SAVE CREATED FROM GAMEMODE
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.

LogTemp: Warning: GAME LOADED FROM GAME INSTANCE! Lenght of hair bool array is 0
LogTemp: Warning: GAME LOADED FROM GAMEMODE
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

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

DDGameInstance.cpp

#include "System/DDSaveGame.h"
#include "Kismet/GameplayStatics.h"
void UDDGameInstance::SaveGame() 
{
	UDDSaveGame* SaveGameRef = Cast<UDDSaveGame>(UGameplayStatics::CreateSaveGameObject(UDDSaveGame::StaticClass()));
	if(SaveGameRef)
	{
		SaveGameRef->FullSave(bHasChest, bHasLegs, bHasFace, bHasHands, bHasHair, bHasBeard, bHasEyebrows, bMaleCharacter, CurrentCoins, SelectedChest, SelectedLegs, SelectedFace, SelectedHands, SelectedHair, SelectedBeard, SelectedEyebrows, SelectedMenuMusic, SelectedGameMusic);
		UGameplayStatics::SaveGameToSlot(SaveGameRef, TEXT("SaveGame"), 0);
		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());
	}
	else{UE_LOG(LogTemp, Error, TEXT("SAVE GAME IS NULL"));}
}

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

void UDDGameInstance::ClearSaveGame() 
{
	UDDSaveGame* SaveGameRef = Cast<UDDSaveGame>(UGameplayStatics::CreateSaveGameObject(UDDSaveGame::StaticClass()));
	if(SaveGameRef)
	{
		bHasChest = {true, false, false, false, false, false, false, true, false, false, false, false};
		bHasLegs = {true, false, false, false, false, false, false, true, false, false, false, false};
		bHasFace = {true, true, true, false, false, true, true, true, false, false};
		bHasHands = {true, false, false, true, false};
		bHasHair = {false, false, false, false, false, false, false, false, false, false, false, false, false, true};
		bHasBeard = {false, false, false, false, true};
		bHasEyebrows = {false, false, false, false, false, false, false, true};
		bMaleCharacter = true;
		bIndestructibleCheat = false;
		CurrentCoins = 0;
		SelectedChest = 0;
		SelectedLegs = 0;
		SelectedFace = 0;
		SelectedHands = 0;
		SelectedHair = 13;
		SelectedBeard = 4;
		SelectedEyebrows = 7;
		SelectedGameMusic = 3;
		SelectedMenuMusic = 0;
		SaveGameRef->FullSave(bHasChest, bHasLegs, bHasFace, bHasHands, bHasHair, bHasBeard, bHasEyebrows, bMaleCharacter, CurrentCoins, SelectedChest, SelectedLegs, SelectedFace, SelectedHands, SelectedHair, SelectedBeard, SelectedEyebrows, SelectedMenuMusic, SelectedGameMusic);
		UGameplayStatics::SaveGameToSlot(SaveGameRef, TEXT("SaveGame"), 0);
	}
	else{UE_LOG(LogTemp, Error, TEXT("SAVEGAMEREF MISSING"));}
}

DDSaveGame.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/SaveGame.h"
#include "DDSaveGame.generated.h"

/**
 * 
 */
UCLASS()
class DESERTDASH_API UDDSaveGame : public USaveGame
{
	GENERATED_BODY()
	
	public:

	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);
	void CoinSave(int Coins);

	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);

	int LenghtOfHairArray();

private:


	TArray<bool> SavedChests;
	TArray<bool> SavedLegs;
	TArray<bool> SavedFaces;
	TArray<bool> SavedHands;
	TArray<bool> SavedHairs;
	TArray<bool> SavedBeards;
	TArray<bool> SavedEyebrows;

	bool bSaveMaleCharacter;

	int CurrentCoins;
	int SelectedChest;
	int SelectedLegs;
	int SelectedFace;
	int SelectedHands;
	int SelectedHair;
	int SelectedBeard;
	int SelectedEyebrows;
	int SelectedGameMusic;
	int SelectedMenuMusic;

};

DDSaveGame.cpp

#include "System/DDSaveGame.h"

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) 
{
	SavedChests = Chests;
    SavedLegs = Legs;
    SavedFaces = Faces;
    SavedHands = Hands;
    SavedHairs = Hairs;
    SavedBeards = Beards;
    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::CoinSave(int Coins) 
{
	CurrentCoins = Coins;
}

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) 
{
	ChestsOUT = SavedChests;
	LegsOUT = SavedLegs;
	FacesOUT = SavedFaces;
	HandsOUT = SavedHands;
	HairsOUT = SavedHairs;
	BeardsOUT = SavedBeards;
	EyebrowsOUT = SavedEyebrows;
	MaleCharacterOUT = bSaveMaleCharacter;
	CoinsOUT = CurrentCoins;
	ChestOUT = SelectedChest;
	LegOUT = SelectedLegs;
	FaceOUT = SelectedFace;
	HandOUT = SelectedHands;
	HairOUT = SelectedHair;
	BeardOUT = SelectedBeard;
	EyebrowOUT = SelectedEyebrows;
	GameMusicOUT = SelectedGameMusic;
	MenuMusicOUT = SelectedMenuMusic;
}

int UDDSaveGame::LenghtOfHairArray() 
{
	return SavedHairs.Num();
}

Thank you again for your help!

It would be nice if this got moderator approval, is it normal for that to take over 18 hours? My previous question was posted immediately and I’m curious why this one wasn’t.

PERFECT! This has approval.

With some help on the forums I have figured out that the issue is not with the content I am trying to save but with the save/load functions them selves.

https://answers.unrealengine.com/questions/1022002/view.html is my new question that I was hoping would get moderator approval before this one since this question is outdated.

TArrays are an Unreal Engine defined type and need to be declared as a UPROPERTY() because strange issues can occur when any (not sure about int8, FVector, etc…) UE defined type is not declared as a UPROPERTY()

Changing any instance of

TArray<bool> BooleanArray;

in header files to

UPROPERTY()
TArray<bool> BooleanArray;

fixed this issue.