Crashing Editor Menu System

I’m getting this error about 2 seconds after I host a game and the editor crashes:

Fatal error: [File:D:/Build/++UE4/Sync/Engine/Source/Runtime/Core/Private/Windows/WindowsPlatformMisc.cpp] [Line: 475] Pure virtual function being called

UE4Editor_Core
VCRUNTIME140
UE4Editor_PuzzlePlatforms_0123!UMainMenu::SetServerList() [X:\PuzzlePlatforms\Source\PuzzlePlatforms\MenuSystem\MainMenu.cpp:103]
UE4Editor_PuzzlePlatforms_0123!UPuzzlePlatformsGameInstance::OnFindSessionsComplete() [X:\PuzzlePlatforms\Source\PuzzlePlatforms\PuzzlePlatformsGameInstance.cpp:181]
UE4Editor_PuzzlePlatforms_0123!TBaseUObjectMethodDelegateInstance<0,UPuzzlePlatformsGameInstance,void __cdecl(bool),FDefaultDelegateUserPolicy>::ExecuteIfSafe() [X:\UnrealEngine\UE_4.27\Engine\Source\Runtime\Core\Public\Delegates\DelegateInstancesImpl.h:611]

here is my MainMenu.cpp and .h:

// Fill out your copyright notice in the Description page of Project Settings.


#include "MainMenu.h"
#include "Components/Button.h"
#include "Components/WidgetSwitcher.h"
#include "UObject/ConstructorHelpers.h"	
#include "Components/EditableTextBox.h"
#include "Components/TextBlock.h"
#include "ServerRow.h"

UMainMenu::UMainMenu(const FObjectInitializer& ObjectInitializer)
{
	ConstructorHelpers::FClassFinder<UUserWidget> ServerRowBPClass(TEXT("/Game/MenuSystem/WBP_ServerRow"));
	if (!ensure(ServerRowBPClass.Class != nullptr)) return;
	ServerRowClass = ServerRowBPClass.Class;
}


bool UMainMenu::Initialize() {
	bool Success = Super::Initialize();
	if (!Success) return false;


	if (!ensure(HostButton != nullptr)) return false;
	HostButton->OnClicked.AddDynamic(this, &UMainMenu::OpenHostMenu);

	if (!ensure(HostButton != nullptr)) return false;
	HostButton->OnClicked.AddDynamic(this, &UMainMenu::OpenHostMenu);

	if (!ensure(CreateSessionButton != nullptr)) return false;
	CreateSessionButton->OnClicked.AddDynamic(this, &UMainMenu::HostServer);

	if (!ensure(PlayButton != nullptr)) return false;
	PlayButton->OnClicked.AddDynamic(this, &UMainMenu::OpenJoinMenu);

	if (!ensure(BackButton != nullptr)) return false;
	BackButton->OnClicked.AddDynamic(this, &UMainMenu::OpenMainMenu);

	if (!ensure(BackButton != nullptr)) return false;
	BackFromHostButton->OnClicked.AddDynamic(this, &UMainMenu::OpenMainMenu);

	if (!ensure(JoinButton != nullptr)) return false;
	JoinButton->OnClicked.AddDynamic(this, &UMainMenu::JoinServer);

	if (!ensure(ExitButton != nullptr)) return false;
	ExitButton->OnClicked.AddDynamic(this, &UMainMenu::ExitPressed);
	return true;
}

void UMainMenu::HostServer()
{
	if (!ensure(MenuInterface != nullptr)) return;
	FString ServerName = (ServerNameTextBox->GetText()).ToString();
	MenuInterface->Host(ServerName);
	UE_LOG(LogTemp, Warning, TEXT("hosting"));
}

void UMainMenu::JoinServer()
{
	if (SelectedIndex.IsSet() && MenuInterface != nullptr) {
		UE_LOG(LogTemp, Warning, TEXT("selected index : %d"), SelectedIndex.GetValue());
		MenuInterface->Join(SelectedIndex.GetValue());
	}
	else {
		UE_LOG(LogTemp, Warning, TEXT("selected index not set"));
	}

}

void UMainMenu::OpenJoinMenu()
{
	UE_LOG(LogTemp, Warning, TEXT("joinclicked"))
	if (!ensure(MenuSwitcher != nullptr)) return;
	if (!ensure(JoinMenu != nullptr)) return;
	MenuSwitcher->SetActiveWidget(JoinMenu);
	if (!ensure(MenuInterface != nullptr)) return;
	MenuInterface->RefreshServerList();
}

void UMainMenu::OpenHostMenu()
{
	UE_LOG(LogTemp, Warning, TEXT("joinclicked"))
	if (!ensure(MenuSwitcher != nullptr)) return;
	if (!ensure(JoinMenu != nullptr)) return;
	MenuSwitcher->SetActiveWidget(HostMenu);
	if (!ensure(MenuInterface != nullptr)) return;
	MenuInterface->RefreshServerList();
}

void UMainMenu::OpenMainMenu()
{
	if (!ensure(MenuSwitcher != nullptr)) return;
	MenuSwitcher->SetActiveWidget(MainMenu);
}

void UMainMenu::SetServerList(TArray<FServerData> ServerNames)
{
	UWorld* World = this->GetWorld();
	if (!ensure(World != nullptr)) return;
	if (!ensure(ServerList != nullptr)) return;
	ServerList->ClearChildren();

	uint32 i = 0;

	for (const FServerData& ServerData : ServerNames)
	{
		UServerRow* ServerRow = CreateWidget<UServerRow>(this, ServerRowClass);
		if (!ensure(ServerRow != nullptr)) return; 

		ServerRow->ServerName->SetText(FText::FromString(ServerData.Name));
		ServerRow->HostUser->SetText(FText::FromString(ServerData.HostUsername));
		FString FractionText = FString::Printf(TEXT("%d/%d"), ServerData.CurrentPlayers, ServerData.MaxPlayers);
		ServerRow->ConnectionFraction->SetText(FText::FromString(FractionText));
		ServerRow->Setup(this, i);
		++i;

		ServerList->AddChild(ServerRow);
	}
}

void UMainMenu::SelectIndex(uint32 Index)
{
	SelectedIndex = Index;
	UpdateChildren();
}

void UMainMenu::UpdateChildren()
{
	for (int32 i = 0; i < ServerList->GetChildrenCount(); ++i) 
	{
		auto Row = Cast<UServerRow>(ServerList->GetChildAt(i));
		if (Row != nullptr)
		{
			Row->Selected = (SelectedIndex.IsSet() && SelectedIndex.GetValue() == i);
		}
	}
}

void UMainMenu::ExitPressed()
{
	UWorld* World = GetWorld();
	if (!ensure(World != nullptr)) return;

	APlayerController* PlayerController = World->GetFirstPlayerController();
	if (!ensure(PlayerController != nullptr)) return;

	PlayerController->ConsoleCommand("quit");
}


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "MenuWidget.h"
#include "Components/EditableTextBox.h"
#include "MainMenu.generated.h"

USTRUCT()
struct FServerData
{
	GENERATED_BODY()

	FString Name;
	
	uint16 CurrentPlayers;
	uint16 MaxPlayers;

	FString HostUsername;
};

/**
 * 
 */
UCLASS()
class PUZZLEPLATFORMS_API UMainMenu : public UMenuWidget
{
	GENERATED_BODY()
	
public:
	UMainMenu(const FObjectInitializer& ObjectInitializer);
	void SetServerList(TArray<FServerData> ServerNames);
	
	void SelectIndex(uint32 Index);
protected:
	virtual bool Initialize() override;

private:

	UPROPERTY(meta = (BindWidget))
		class UButton* HostButton;

	UPROPERTY(meta = (BindWidget))
		class UButton* PlayButton;

	UPROPERTY(meta = (BindWidget))
		class UButton* JoinButton;

	UPROPERTY(meta = (BindWidget))
		class UButton* BackButton;

	UPROPERTY(meta = (BindWidget))
		class UButton* ExitButton;
	
	UPROPERTY(meta = (BindWidget))
		class UButton* BackFromHostButton;

	UPROPERTY(meta = (BindWidget))
		class UEditableTextBox* ServerNameTextBox;

	UPROPERTY(meta = (BindWidget))
		class UButton* CreateSessionButton;

	UPROPERTY(meta = (BindWidget))
		class UWidgetSwitcher* MenuSwitcher;

	UPROPERTY(meta = (BindWidget))
		class UWidget* JoinMenu;

	UPROPERTY(meta = (BindWidget))
		class UWidget* HostMenu;

	UPROPERTY(meta = (BindWidget))
		class UWidget* MainMenu;

	UPROPERTY(meta = (BindWidget))
		class UPanelWidget* ServerList;

	TSubclassOf<class UUserWidget> ServerRowClass;
	TOptional<uint32> SelectedIndex;

	UFUNCTION()
		void HostServer();

	UFUNCTION()
		void JoinServer();

	UFUNCTION()
		void OpenJoinMenu();

	UFUNCTION()
		void OpenHostMenu();

	UFUNCTION()
		void OpenMainMenu();

	UFUNCTION()
		void ExitPressed();

	void UpdateChildren();
};

even if i comment out the ServerList->ClearChildren() it still gives me the same error but on a different line. If someone knows what goes wrong, please help :slightly_smiling_face:

1 Like

Try these following steps

  • Confirm the ServerList is named this in the widget blueprint and not been changed.
  • Setthe widget blueprint class back to a base (UUserWidget) and then back to UMenuWidget.
  • If you comment out the code in SetServerList except for the GetWorld call, and I appreciate that disables everything, does it still crash?
  • Close the editor, delete the binaries folder and open the uproject which will rebuild

The code itself looks fine so it may be one of these things.

1 Like

I rebuilt the project and it seems to be working now. Thanks!

1 Like

That’s always a good one to try. Glad you’re sorted.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.