Hey everyone. I’m trying to create a custom Game Instance class in C++, but I’ve run into a bit of a problem.
After compiling my class, my log outputs a copy of 4 “LogUObjectBase: Error: ‘this’ pointer is invalid.” errors.
I saw this post earlier, but it hasn’t seemed to help much. I’ve double checked my class and I seem to have all of my variables and methods properly macro-ed with UPROPERTY() and UFUNCTION(). ShadowRiver mentioned using the RF_RootSet flag to prevent a class from being garbage collected, but:
A) I can’t see to find this flag in VS for Unreal Version 4.18
and
B) I’m pretty sure a standard Game Instance class shouldn’t need this to avoid garbage collection ( though I could be wrong). Pasting my code below. Can someone explain what I’m doing wrong and why?
My Class:
h
#pragma once
#include "UMG.h"
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "FastTT_GameInstance.generated.h"
/**
*
*/
UCLASS()
class GAMEOFCLONES_API UFastTT_GameInstance : public UGameInstance
{
GENERATED_BODY()
public:
DECLARE_EVENT(UFastTT_GameInstance, ShowLobbyGUI)
UFastTT_GameInstance();
protected:
/**
* The UMG GUI widget to be displayed for the game's main menu
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widget Templates")
TSubclassOf<UUserWidget> MainMenuGUIWidget;
/**
* Reference to instantiated Main Menu GUI Widget
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widgets")
UUserWidget* MainMenuWidgetRef;
/**
* The UMG GUI widget displayed in the game's multiplayer lobbys
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widget Templates")
TSubclassOf<UUserWidget> LobbyGUIWidget;
/**
* Reference to instantiated Lobby GUI Widget
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widgets")
UUserWidget* LobbyWidgetRef;
/**
* The UMG GUI widget used to select settings for the game session to be
* created. Should have options such as game type, map, num players, etc.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widget Templates")
TSubclassOf<UUserWidget> HostSettingsGUIWidget;
/**
* The UMG GUI widget used to select a server (ie. game session) to join Should be displayed on a client trying to pick and join a game session
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Widget Templates")
TSubclassOf<UUserWidget> ServerListGUIWidget;
/**
* The maximum number of players allowed to join the game.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Game Settings")
int32 MaxPlayers;
/**
* The name of the session to create
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Game Settings")
FText ServerName;
/**
* Name of the UMap used as the game's lobby
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Game Settings")
FName LobbyLevelName;
public:
#pragma region Accessors and Mutators
#pragma region GUI
/**
* Gets a pointer to the UMG widget containing the GUI that is
* displayed in multiplayer session lobbies.
* @see UWidget* UFastTT_GameInstance::LobbyGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> GetLobbyGUIWidget();
/**
* Set a pointer to the UMG widget containing the GUI that is
* displayed in multiplayer session lobbies.
* @see UWidget* UFastTT_GameInstance::LobbyGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> SetLobbyGUIWidget(TSubclassOf<UUserWidget> NewWidget);
/**
* Sets a pointer to the UMG widget containing the GUI that is
* displayed as the game's main menu.
* @see UWidget* UFastTT_GameInstance::MainMenuGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> GetMainMenuGUIWidget();
/**
* Sets a pointer to the UMG widget containing the Host Settings GUI that is
* used to set session settings such as as game type, map, num players, etc.
* @see UWidget* UFastTT_GameInstance::HostSettingsGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> SetMainMenuGUIWidget(TSubclassOf<UUserWidget> NewWidget);
/**
* Gets a pointer to the UMG widget containing the Host Settings GUI that is
* used to set session settings such as as game type, map, num players, etc.
* @see UWidget* UFastTT_GameInstance::HostSettingsGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> GetHostSettingsGUIWidget();
/**
* Sets a pointer to the UMG widget containing the Host Settings GUI that is
* used to set session settings such as as game type, map, num players, etc.
* @see UWidget* UFastTT_GameInstance::HostSettingsGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> SetHostSettingsGUIWidget(TSubclassOf<UUserWidget> NewWidget);
/**
* Gets a pointer to the UMG widget containing the Host Settings GUI that is
* used to set session settings such as as game type, map, num players, etc.
* @see UWidget* UFastTT_GameInstance::HostSettingsGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> GetServerListGUIWidget();
/**
* Sets a pointer to the UMG widget containing the Host Settings GUI that is
* used to set session settings such as as game type, map, num players, etc.
* @see UWidget* UFastTT_GameInstance::HostSettingsGUIWidget
*/
UFUNCTION(BlueprintCallable)
TSubclassOf<UUserWidget> SetServerListGUIWidget(TSubclassOf<UUserWidget> NewWidget);
#pragma endregion
#pragma endregion
/**
* Shows or hides the MainMenuGUIWidget by attaching the LobbyGUIWidget to the parent view.
*/
UFUNCTION(BlueprintCallable)
void ShowMainMenuGUI(bool show);
/**
* Shows or hides the LobbyGUIWidget by attaching the LobbyGUIWidget to the parent view.
*/
UFUNCTION(BlueprintCallable)
void ShowLobbyGUI(bool show);
/**
* Fills GUI widget variables with instances of the widget classes specified.
*/
UFUNCTION(BlueprintCallable)
void PopulateWidgetInstances();
/**
* Checks if Ref is already filled and valid, and if it isn't creates a new
* Widget of the template classand returns a UUserWidget pointer to it.
*/
UFUNCTION()
void CreateWidgetFromTemplate(TSubclassOf<UUserWidget> templateWidget, UUserWidget* ref);
/**
*
*/
UFUNCTION()
void ToggleGUIWidget(bool show, UUserWidget* WidgetToToggle);
private:
};
c++
#include "FastTT_GameInstance.h"
UFastTT_GameInstance::UFastTT_GameInstance()
{
this->SetFlags(RF_);
PopulateWidgetInstances();
}
#pragma region Accessors and Mutators
#pragma region GUI
TSubclassOf<UUserWidget> UFastTT_GameInstance::GetLobbyGUIWidget()
{
return LobbyGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::SetLobbyGUIWidget(TSubclassOf<UUserWidget> NewWidget)
{
LobbyGUIWidget = NewWidget;
return LobbyGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::GetMainMenuGUIWidget()
{
return MainMenuGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::SetMainMenuGUIWidget(TSubclassOf<UUserWidget> NewWidget)
{
MainMenuGUIWidget = NewWidget;
return LobbyGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::GetHostSettingsGUIWidget()
{
return HostSettingsGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::SetHostSettingsGUIWidget(TSubclassOf<UUserWidget> NewWidget)
{
HostSettingsGUIWidget = NewWidget;
return HostSettingsGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::GetServerListGUIWidget()
{
return ServerListGUIWidget;
}
TSubclassOf<UUserWidget> UFastTT_GameInstance::SetServerListGUIWidget(TSubclassOf<UUserWidget> NewWidget)
{
ServerListGUIWidget = NewWidget;
return ServerListGUIWidget;
}
#pragma endregion
#pragma endregion
void UFastTT_GameInstance::ShowMainMenuGUI(bool show)
{
ToggleGUIWidget(show, MainMenuWidgetRef);
}
void UFastTT_GameInstance::ShowLobbyGUI(bool show)
{
UE_LOG(LogTemp, Warning, TEXT("ShowLobbyGUI"));
ToggleGUIWidget(show, LobbyWidgetRef);
}
void UFastTT_GameInstance::ToggleGUIWidget(bool show, UUserWidget* WidgetToToggle)
{
if (!WidgetToToggle->IsValidLowLevel())
{
PopulateWidgetInstances();
if (!WidgetToToggle->IsValidLowLevel())
{
UE_LOG(LogTemp, Error, TEXT("ToggleGUIWidget was called with an invalid WidgetToToggle"));
return;
}
}
if (show == false)
{
WidgetToToggle->RemoveFromViewport();
}
else
{
WidgetToToggle->AddToViewport();
}
}
void UFastTT_GameInstance::PopulateWidgetInstances()
{
CreateWidgetFromTemplate(MainMenuGUIWidget, MainMenuWidgetRef);
CreateWidgetFromTemplate(LobbyGUIWidget, LobbyWidgetRef);
}
void UFastTT_GameInstance::CreateWidgetFromTemplate(TSubclassOf<UUserWidget> templateWidget, UUserWidget* ref)
{
//Check if widget template has a valid value
if (templateWidget->IsValidLowLevelFast())
{
if (ref->IsValidLowLevel())
{
//Do Nothing, Reference to an existing widget already exists
}
else
{
ref = CreateWidget<UUserWidget>(this, templateWidget);
}
}
else if (!LobbyGUIWidget->IsValidLowLevelFast())
{
}
else
{
}
}