Unreal Engine C++开发Pong游戏:不使用Level Blueprint如何显示UMG主菜单?
Hey there! Great question—moving away from Level Blueprints for your main menu logic is a fantastic call for keeping your Pong project clean and easy to maintain as you expand it. Let’s break down the most common, industry-standard approaches to handle this in C++:
1. Custom Game Mode Class
Game Modes are the go-to for handling game session initialization, so this is perfect for showing your main menu when the game starts. Here’s how to set it up:
- Create a new C++ class inheriting from
AGameModeBase(name something likeAPongGameMode) - In its
BeginPlay()method, add code to load and spawn your main menu widget - Set this Game Mode as your project’s default in Project Settings > Maps & Modes
Example Code
Header (.h)
#pragma once #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "PongGameMode.generated.h" UCLASS() class PONG_API APongGameMode : public AGameModeBase { GENERATED_BODY() protected: // Runs when the game session starts virtual void BeginPlay() override; private: // Assign your main menu widget blueprint here in the editor UPROPERTY(EditAnywhere, Category = "UI") TSubclassOf<class UUserWidget> MainMenuWidgetClass; // Keep a reference to the spawned menu widget UUserWidget* CurrentMainMenu; };
Source (.cpp)
#include "PongGameMode.h" #include "UI/MainMenuWidget.h" // Replace with your widget's header #include "Kismet/GameplayStatics.h" void APongGameMode::BeginPlay() { Super::BeginPlay(); // Only proceed if we've assigned a widget class in the editor if (MainMenuWidgetClass) { CurrentMainMenu = CreateWidget<UUserWidget>(GetWorld(), MainMenuWidgetClass); if (CurrentMainMenu) { // Add the menu to the screen CurrentMainMenu->AddToViewport(); // Configure input to work with the menu (mouse cursor, UI focus) APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0); if (PlayerController) { FInputModeUIOnly InputMode; InputMode.SetWidgetToFocus(CurrentMainMenu->TakeWidget()); InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::LockInFullscreen); PlayerController->SetInputMode(InputMode); PlayerController->SetShowMouseCursor(true); } } } }
2. Custom Game Instance Class
Game Instances exist for the entire lifespan of your game (not just a single level), so this is ideal if you want to show the menu before any level loads, or keep it persistent across level switches.
- Create a C++ class inheriting from
UGameInstance(name likeUPongGameInstance) - Override the
Init()method to spawn your menu - Set this as your default Game Instance in Project Settings > Project > Game Instance Class
Example Code
Header (.h)
#pragma once #include "CoreMinimal.h" #include "Engine/GameInstance.h" #include "PongGameInstance.generated.h" UCLASS() class PONG_API UPongGameInstance : public UGameInstance { GENERATED_BODY() public: // Runs when the game first starts up virtual void Init() override; private: UPROPERTY(EditAnywhere, Category = "UI") TSubclassOf<class UUserWidget> MainMenuWidgetClass; UUserWidget* MainMenuWidget; };
Source (.cpp)
#include "PongGameInstance.h" #include "UI/MainMenuWidget.h" #include "Kismet/GameplayStatics.h" void UPongGameInstance::Init() { Super::Init(); if (MainMenuWidgetClass) { MainMenuWidget = CreateWidget<UUserWidget>(this, MainMenuWidgetClass); if (MainMenuWidget) { MainMenuWidget->AddToViewport(); // Set up input for the menu APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0); if (PlayerController) { FInputModeUIOnly InputMode; InputMode.SetWidgetToFocus(MainMenuWidget->TakeWidget()); PlayerController->SetInputMode(InputMode); PlayerController->SetShowMouseCursor(true); } } } }
3. Custom Player Controller Class
Player Controllers handle player input and view management, so this works well if your menu is tied to player-specific actions (like pressing a key to open a pause menu). For your main menu, it’s still a valid option—especially if you want to handle menu input logic directly in the Player Controller.
- Create a C++ class inheriting from
APlayerController(name likeAPongPlayerController) - Spawn the menu in
BeginPlay()or a custom input handler
Example Code
Header (.h)
#pragma once #include "CoreMinimal.h" #include "GameFramework/PlayerController.h" #include "PongPlayerController.generated.h" UCLASS() class PONG_API APongPlayerController : public APlayerController { GENERATED_BODY() protected: virtual void BeginPlay() override; private: UPROPERTY(EditAnywhere, Category = "UI") TSubclassOf<class UUserWidget> MainMenuWidgetClass; UUserWidget* MainMenuWidget; };
Source (.cpp)
#include "PongPlayerController.h" #include "UI/MainMenuWidget.h" void APongPlayerController::BeginPlay() { Super::BeginPlay(); if (MainMenuWidgetClass) { MainMenuWidget = CreateWidget<UUserWidget>(this, MainMenuWidgetClass); if (MainMenuWidget) { MainMenuWidget->AddToViewport(); SetInputMode(FInputModeUIOnly()); SetShowMouseCursor(true); } } }
Quick Tips to Keep in Mind
- Use
TSubclassOf<UUserWidget>to reference your widget blueprint—this lets you assign it directly in the Unreal Editor without hardcoding file paths. - Always configure the input mode when showing the menu:
FInputModeUIOnlyensures the mouse interacts with the menu instead of the game world, andSetShowMouseCursor(true)makes the cursor visible. - For your Pong game, starting with a Custom Game Mode is likely the simplest choice—it ties the menu initialization directly to the start of your game session, which is exactly what you need for a main menu.
内容的提问来源于stack exchange,提问作者VansFannel




