Timothy Marks Memoji

Timothy Marks

@imothee

Hi, I'm Tim, an engineer, founder, leader and hacker. Here you'll find my articles, apps, projects and open source stuff

Serfs_Up_Main_Menu

Serfs Up 04 - Main Menu

Building an in game, rendered Main Menu screen in Unreal

Building an animated Main Menu screen in Unreal

In this tutorial we'll walk through building an in game MainMenu screen inside of Unreal Engine. So far in my gaming and game design experience there are two main kind of menu screens I've experienced. The first is a Widget only menu, where the background is a static or animated image and the entire menu is just composed as an interface. The second is where there is a menu "level" created with a set of actors and static meshes that limit player control. I'm excited to play with the latter so this tutorial will focus on an in game rendered level main menu.

Kick things off by going to File, New Level. We'll create an empty level and build everything from scratch. Once the new level has loaded, hit save and call your new level MainMenu. You should now have a completely empty level.

Let there be light

The first thing we need is some light in our level so we're going to use the awesome Env. Light Mixer window to bootstrap some lighting. Go to the Window Menu and open the Env. Light Mixer. We're going to be adding

  • Directional Light (This is our pretend sun)
  • Skylight (Brightens the entire world by a base amount)
  • SkyAtmosphere (Makes it look like we have a sky)
  • VolumetricCloud (Clouds in the sky)
  • ExponentialHeightFog (Makes the world feel more real)
  • SkySphere (Not sure what this is yet TODO)

If you click on each in the Env. Light Mixer you'll soon see a panel of each of the lighting options added to your level. For now we can leave the defaults.

Land Ho

The second thing our level needs is some land. Open LandScape mode by grabbing the "Selection Mode" dropdown and choose Landscape or press Shift + 2. Once you're in Landscape mode, we're going to create a 3x3 landscape with the default settings and hit create.

For our Main Menu level, I want to have some mountains and forests in the background so let's start by using the sculpt tool to add some random height to the level. Go wild, there's no wrong answers here and when you're done you should have something in the general vicinity of

Stage a scene

If you don't have an asset pack already now would be a good time to track one down, for this tutorial we're using Advanced Village Pack but really anything works. Drag and drop your environment and props and set your landscape material until you've staged a reasonable backdrop to your main menu.

Mine looks like this but you don't need to add as much detail for your own version just yet. You can curate, craft and sweat the small details later as much as you like.

Staged_Menu_Scene

Creating the MainMenuHUD Widget

Now that we've got our scene staged we can start to work on the interface itself. Create a new Widget actors

SerfsUp/Core/UserInteface/WBP_MainMenuHUD

For now let's keep it super simple and just create a Canvas panel with a vertical box, the game title and 3 buttons.

Lastly, this is not production ready at all since opening a level this way runs in the main thread and will effectively just pause your game until the loading is done but lets hook up an open level event to the new game button on click event.

Creating the MainMenuHUD HUD class

We need to setup a HUD that's specific to our main menu. The difference between this and the GameHUD is that the MainMenuHUD will not implement our GameHUDInterface and will not allow the player to interact with the Character.

Public/Game/MainMenuHUD.h
// This work is licensed under a Creative Commons Attribution 4.0 International License https://creativecommons.org/licenses/by/4.0/

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "Blueprint/UserWidget.h"
#include "MainMenuHUD.generated.h"

/**
 *
 */
UCLASS()
class SERFSUP_API AMainMenuHUD : public AHUD
{
  GENERATED_BODY()

public:
  AMainMenuHUD();

protected:
  // To add mapping context
  virtual void BeginPlay();

private:
  /* Widget */
  TSubclassOf<class UUserWidget> HUDWidgetClass;
  UUserWidget *HUDWidget;
};
Private/Game/MainMenuHUD.cpp
// This work is licensed under a Creative Commons Attribution 4.0 International License https://creativecommons.org/licenses/by/4.0/

#include "Game/MainMenuHUD.h"

AMainMenuHUD::AMainMenuHUD()
{
  ConstructorHelpers::FClassFinder<UUserWidget> WidgetClassFinder(TEXT("WidgetBlueprint'/Game/SerfsUp/Core/UserInterface/WBP_MainMenuHUD'"));
  if (WidgetClassFinder.Succeeded())
  {
    HUDWidgetClass = WidgetClassFinder.Class;
  }
}

void AMainMenuHUD::BeginPlay()
{
  // Call the base class
  Super::BeginPlay();

  // Create our HUDWidget
  HUDWidget = CreateWidget<UUserWidget>(PlayerOwner, HUDWidgetClass);
  // Add it to the viewport to be rendered
  HUDWidget->AddToViewport(0);

  // Set the input mode to UI only
  PlayerOwner->SetInputMode(FInputModeUIOnly());
  // Show the mouse cursor for the player
  PlayerOwner->SetShowMouseCursor(true);
}

Creating the MainMenuGameMode

Similar to the HUD class above, we want to have a separate GameMode that sets a lot of the game options to more useful defaults for a non-interactable level.

Public/Game/SerfsUpMainMenuMode.h
// This work is licensed under a Creative Commons Attribution 4.0 International License https://creativecommons.org/licenses/by/4.0/

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "SerfsUpMainMenuMode.generated.h"

UCLASS(minimalapi)
class ASerfsUpMainMenuMode : public AGameModeBase
{
  GENERATED_BODY()

public:
  ASerfsUpMainMenuMode();
};
Private/Game/SerfsUpMainMenuMode.cpp
// This work is licensed under a Creative Commons Attribution 4.0 International License https://creativecommons.org/licenses/by/4.0/

#include "Game/SerfsUpMainMenuMode.h"
#include "Game/MainMenuHUD.h"
#include "UObject/ConstructorHelpers.h"

ASerfsUpMainMenuMode::ASerfsUpMainMenuMode()
{
  // Setup the HUD
  HUDClass = AMainMenuHUD::StaticClass();
  // We don't set our PlayerController or PlayerCharacter or Pawn as the default ones are just fine for this scene

  // Set the game mode to start all players as spectators so we load pawns instead of the PlayerCharacter
  bStartPlayersAsSpectators = true;
}

Camera, Action

Now that all of the core classes exist, it's time to put it all together, add a camera and setup our level to be our new default level for the program.

Open the MainMenu level and go to WorldDetails and change the GameMode Override to SerfsUpMainMenuMode per below. You'll see all the default GameMode objects setup.

The last step now is to add a default Camera to the level that will be our viewpoint into the MainMenu scene. Add a new CameraActor and position it wherever looks best, I named the camera MenuCamera and set it to slightly above the scene.

To set the MenuCamera to be the default camera we need to open the Level Blueprint

We want to call Set View Target with Blend on Event BeginPlay and set the New View Target to be MenuCamera

Fin

Et Voila

February 04, 2023

0

🕛 6

© 2022 - 2023, Built by @imothee