User Interface With UMG

Create a simple menu system using UMG.

Windows
MacOS
Linux

Over the course of this tutorial, you will learn to use Unreal Motion Graphics (UMG) to build a basic menu system with multiple screens and buttons.

1. Set Up Module Dependencies for UMG

If you are new to Unreal Engine 4, you might want to read our Programming Quick Start tutorial first. For this tutorial, we will assume you are familiar with creating a project, adding C++ code to it, and compiling your code. We will also expose functions and properties to Blueprint. If you would like to learn more about that, the Variables, Timers, and Events tutorial is a good place to start.

  1. We will begin by creating a new project:

    • Select the C++ tab.

    • Select Basic Code.

    • Leave the default values of Desktop/Console and With Starter Content.

    • We will use the name HowTo_UMG.

    UMG_ProjectSetup.png

    Since we're going to write code that uses Unreal Motion Graphics (UMG), we'll need to go into Visual Studio include a few modules that aren't available by default.

  2. We can get to our project's code by using the Open Visual Studio command from the File dropdown menu on the main editor screen.

    OpenVisualStudio.png

  3. UMG is dependent on a few modules, so we'll need to add those modules to HowTo_UMG.Build.cs.

    BuildCS.png

    In HowTo_UMG.Build.CS, we need to add UMG to the list of included public modules, and Slate and SlateCore to the list of included private modules. We'll need to modify the first line in HowTo_UMG's constructor to read as follows:

    PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });

    And then we can uncomment the following line:

    PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

    As usual, full source code is provided below so you can double-check your code.


With UMG set up, we can add code to our project's custom Game Mode to create and display our game's menus.

Work-In-Progress Code

HowTo_UMG.Build.cs

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class HowTo_UMG : ModuleRules
{
    public HowTo_UMG(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });

        //PrivateDependencyModuleNames.AddRange(new string[] {  });

        // Uncomment if you are using Slate UI
        PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");
        // if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64))
        // {
        //      if (UEBuildConfiguration.bCompileSteamOSS == true)
        //      {
        //          DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
        //      }
        // }
    }
}

2. Extend Our Game Mode

  1. The menus we create will be made from User Widgets. We'll need to write a function that creates and displays a new User Widget, and then call that function when the game starts. We'll also need to keep track of what we have created so that we can remove it later. Since each project already comes with a custom GameMode class, we can simply open ours, which is defined in HowTo_UMGGameMode.h. The following functions and properties will need to be added to the bottom of the class:

    public:
        /** Remove the current menu widget and create a new one from the specified class, if provided. */
        UFUNCTION(BlueprintCallable, Category = "UMG Game")
        void ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass);
    
    protected:
        /** Called when the game starts. */
        virtual void BeginPlay() override;
    
        /** The widget class we will use as our menu when the game starts. */
        UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG Game")
        TSubclassOf<UUserWidget> StartingWidgetClass;
    
        /** The widget instance that we are using as our menu. */
        UPROPERTY()
        UUserWidget* CurrentWidget;
  2. In order to use User Widgets in our code, and add the following line to the top of the #include section:

    #include "Blueprint/UserWidget.h"
  3. Moving to HowTo_UMGGameMode.cpp now, we need to fill out the bodies of the two functions we declared. We'll start with overriding BeginPlay():

    void AHowTo_UMGGameMode::BeginPlay()
    {
        Super::BeginPlay();
        ChangeMenuWidget(StartingWidgetClass);
    }

    When overriding functions from a parent class (referenced by the word Super), as we do here with BeginPlay, it is often important to call the parent class' version of that function. Since our version of the function is only meant to add one step to the end of the existing procedure, we call Super::BeginPlay in the first line of the function.

  4. Next, still in HowTo_UMGGameMode.cpp, we need to define how we change between menus. We will need to remove whatever User Widget we have active from the viewport, if any. Then we can create and a new User Widget and add it to the viewport.

    void AHowTo_UMGGameMode::ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass)
    {
        if (CurrentWidget != nullptr)
        {
            CurrentWidget->RemoveFromViewport();
            CurrentWidget = nullptr;
        }
        if (NewWidgetClass != nullptr)
        {
            CurrentWidget = CreateWidget<UUserWidget>(GetWorld(), NewWidgetClass);
            if (CurrentWidget != nullptr)
            {
                CurrentWidget->AddToViewport();
            }
        }
    }

    This code will create instances of any Widgets we provide and put them on the screen. It also removes them, so that only one is active at a time, although Unreal Engine can handle displaying and interacting with many Widgets at once. We never need to destroy a Widget directly, because removing it from the viewport and clearing (or changing) all variables that reference it will cause it to be cleaned up by Unreal Engine's garbage collection system.

  5. Finally, we need to set the input mode on our Player Controller class. To do this, we'll add a new C++ class to our project, based on Player Controller. Within this class, we only need to call one extra function when the game starts to ensure that we can interact with UI elements.

    NewClass.png PlayerController.png

    In HowTo_UMGPlayerController.h, we will add the following override to the class:

    public:
        virtual void BeginPlay() override;

    In HowTo_UMGPlayerController.cpp, we will add our overridden function:

    void AHowTo_UMGPlayerController::BeginPlay()
    {
        Super::BeginPlay();
        SetInputMode(FInputModeGameAndUI());
    }

We have built the code framework to create and display menus, and remove them when they are no longer needed. We're ready to return to the Unreal Editor and design our menu assets!

Finished Code

HowTo_UMG.Build.cs

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class HowTo_UMG : ModuleRules
{
    public HowTo_UMG(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });

        //PrivateDependencyModuleNames.AddRange(new string[] {  });

        // Uncomment if you are using Slate UI
        PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");
        // if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64))
        // {
        //      if (UEBuildConfiguration.bCompileSteamOSS == true)
        //      {
        //          DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
        //      }
        // }
    }
}

HowTo_UMGGameMode.h

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Blueprint/UserWidget.h"
#include "GameFramework/GameModeBase.h"
#include "HowTo_UMGGameMode.generated.h"

/**
    * 
    */
UCLASS()
class HOWTO_UMG_API AHowTo_UMGGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    /** Remove the current menu widget and create a new one from the specified class, if provided. */
    UFUNCTION(BlueprintCallable, Category = "UMG Game")
    void ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass);

protected:
    /** Called when the game starts. */
    virtual void BeginPlay() override;

    /** The widget class we will use as our menu when the game starts. */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG Game")
    TSubclassOf<UUserWidget> StartingWidgetClass;

    /** The widget instance that we are using as our menu. */
    UPROPERTY()
    UUserWidget* CurrentWidget;
};

HowTo_UMGGameMode.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_UMG.h"
#include "HowTo_UMGGameMode.h"

void AHowTo_UMGGameMode::BeginPlay()
{
    Super::BeginPlay();
    ChangeMenuWidget(StartingWidgetClass);
}

void AHowTo_UMGGameMode::ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass)
{
    if (CurrentWidget != nullptr)
    {
        CurrentWidget->RemoveFromViewport();
        CurrentWidget = nullptr;
    }
    if (NewWidgetClass != nullptr)
    {
        CurrentWidget = CreateWidget<UUserWidget>(GetWorld(), NewWidgetClass);
        if (CurrentWidget != nullptr)
        {
            CurrentWidget->AddToViewport();
        }
    }
}

HowTo_UMGPlayerController.h

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/PlayerController.h"
#include "HowTo_UMGPlayerController.generated.h"

/**
    * 
    */
UCLASS()
class HOWTO_UMG_API AHowTo_UMGPlayerController : public APlayerController
{
    GENERATED_BODY()

public:
    virtual void BeginPlay() override;
};

HowTo_UMGPlayerController.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_UMG.h"
#include "HowTo_UMGPlayerController.h"

void AHowTo_UMGPlayerController::BeginPlay()
{
    Super::BeginPlay();
    SetInputMode(FInputModeGameAndUI());
}

3. Create Menu Widget Blueprints

  1. In Unreal Editor, we can press the Compile button to build our new code. This will allow us to use User Widgets as menus.

    CompileFromEditor.png

  2. We will now create the User Widgets that our GameMode will use as menus. This is done with the Add New button in the Content Browser. The Widget Blueprint class is found in the User Interface category. We need to create two of these, one named MainMenu and one named NewGameMenu. Our game will begin at the Main Menu, and will have an option to proceed to the New Game Menu.

    CreateWidgetBP.png

  3. Double-clicking the MainMenu Widget we've just created will take us to the Blueprint Designer, where we can create our menu layout.

  4. Let's drag a Button and a Text from the Common section of the Palette Panel to the Graph. This Button will eventually be used to open the New Game Menu.

    AddButtonAndTextBlock.png

  5. The first step in making our layout look right is to adjust the location and size of our Button. We should make the following changes:

    • Set the size to 200x200.

    • Set the position to (200, 100).

    • Rename it NewGameButton, just to make it easier to recoginze when we hook up functionality to it later on.

    ButtonDetails.png

  6. Since we're not drawing a custom set of images for the Button, we can label it by dragging and dropping the Text Block onto it and making the following changes:

    • Set the text to say New Game.

    • Change the Visibility to Hit Test Invisible. This will prevent the Text Block from intercepting mouse-clicks that are intended for the Button underneath.

    • Set the name to NewGameText. This is not needed, but it's a good habit.

    TextBlockDetails.png

  7. Next, we'll want to make a "Quit" feature with a second Button and Text Block. Set those up in the same way as the New Game Button and Text Block except the following changes.

    • Set the name of the Button to QuitButton

    • Set the position of the button to 600, 100

    • Set the name of the Text Block to QuitText

  8. After that, we can add Events to our Buttons so that we can run code when a Button is clicked. This is done by locating and pressing the + next to the appropriate Event name in the Details Panel. In this case, OnClicked is the event we want to use. Create this event for both the NewGameButton amd QuitButton Widgets.

    CreateOnClickedEvent.png

    Designers can build functionality with Blueprint scripting here, or C++ programmers can connect nodes that call exposed functions.

  9. For the Event called OnClicked(NewGameButton), we'll want to:

    • Connect a ChangeMenuWidget node to use the function we added to our GameMode earlier.

    • Set the New Widget Class field on the ChangeMenuWidget node to the NewGameMenu asset.

    OnClicked_NewGame.png

  10. For the OnClicked(QuitButton) Event, we'll want to:

    • Connect a Quit Game node.

    OnClicked_Quit.png

With our main menu built, we can set up a GameMode asset that will load it as soon as the level starts.

4. Configure Our Game Mode

  1. In the Content Browser, we will add a Blueprint Class based on our project's GameMode. This makes it possible to set the exposed variables on those two classes to whatever values we want. To do this:

    • Click the Add button in the Content Browser.

    AddNewBPClass.png

    • Pick HowTo_UMGGameMode as the parent class. It will be listed in the All Classes section.

    PickParentClassForGameModeBP.png

    • Name the resulting Blueprint asset MenuGameMode.

  2. In order to see our mouse cursor in-game, we'll need to create a Blueprint of the PlayerController as we did with our GameMode.

    • Click the Add button in the Content Browser again.

    • Select Player Controller from the Common Classes section.

    • Name the Blueprint MenuPlayerController.

  3. Edit MenuPlayerController.

    • Check the Show Mouse Cursor box.

    GamePlayerController.png

  4. Edit MenuGameMode.

    • The Starting Widget Class must be set to the MainMenu asset in order to bring up our menu when the game begins.

    • The Default Pawn Class should be set to Pawn instead of DefaultPawn so that our player will not be able to fly around while in the menu.

    • The Player Controller Class should be set to the MenuPlayerController asset we created so that the mouse cursor will be shown in-game.

    ConfigureGameMode.png

  5. In order for our Blueprint to be used, we must return to the Level Editor window and change the World Settings for our current Level via the Settings button.

    WorldSettingsBar.png

    It is also possible to set the default GameMode in the Project Settings menu, under the Maps and Modes section. If you use this method, all of your levels will default to the GameMode you choose, unless overridden individually. Which method you use depends on how you prefer to set up your project.

  6. The World Settings Panel will open up. By default, it will be docked with the Details Panel, but it can be moved elsewhere. We need to set the Game Mode Override field to our MenuGameMode asset.

    WorldSettings.png

Our custom GameMode asset is now in effect on our level, configured to load our Main Menu, and use our Player Controller that shows the mouse cursor. If we run the game now, our Quit button will work as expected, and our New Game button will take us to an empty menu screen. Our next step will be to set up the New Game menu.

5. Build A Second Menu

  1. In the Content Browser, find and open the NewGameMenu asset we created earlier. This menu will contain a name-entry Text Box, a Button to play the game that cannot be pressed until a name is entered, and a Button to return to the main menu.

  2. To create the name entry box, we'll drag a Text Box (not a Text Block) into the layout.

    CreateTextEntryBox.png

  3. The Text Box should be configured with the following values:

    • Change the name to NameTextEntry

    • Position is (325, 200). This leaves room for a Text Block placed to the left of the Text Box.

    • Size is 250x40.

    • Font Size (under the "Style" heading) is 20.

    TextBoxDetails.png

  4. We can create the Play Game Button with a Text Block label the same way we created the Buttons on the previous menu.

    • For the Button: Change the name to PlayGameButton, Position to 200, 300, Size to 200, 100

    • For the Text Block: Change the name to PlayGameText, set Visibility to Hit Test Visible, and drag it on top of the PlayGameButton

  5. The Play Game Button will have a special feature - it will be enabled only when the name entered in the Text Box is not empty. We can use Unreal Motion Graphics' (UMG) bind feature to create a new function for the Is Enabled field (under the Behavior section).

    PlayGameButtonDetails.png

    If there were complex rules for determining what constitutes a valid player name in our game, or if we needed to save the name to a C++ variable, we might expose a UFUNCTION on our GameMode or as a static function somewhere within our project. However, since we only care that the name string is not empty, we can script it right here in our Widget.

  6. To ensure that the Button is enabled if and only if the Text Box is not empty, we can convert the text from the Text Box to a string and then check that its length is greater than zero. Here is how that logic would appear:

    PlayGameButtonEnableFunction.png

  7. Let's add one more Button so we can back out and get to our Main Menu from here. This will be just like the Play Game Button from our Main Menu, but it will be positioned relative to the lower-right corner instead of the upper-left. To accomplish this, click the Anchors dropdown in the Details Panel for the Button and find the appropriate graphical representation in the pop-up menu.

    • Change the name to MainMenuButton

    • Set the Position to -400, -200

    • Set the Size to 200x100

    SelectAnchor.png

    Positioning our anchor at the lower-right corner does not change how size and position values work, so we'll need to make our position values negative in order to be on the screen. Size values will remain positive.

  8. We will now add scripting to our new Buttons by once again adding OnClicked events. The Main Menu Button will simply reload the Main Menu Widget, while the Play Game Button will deactivate our menu entirely by having no new Widget provided in the call to our ChangeMenuWidget function. This is shown by the phrase Select Class being displayed instead of the name of an actual class or asset.

    NewGameButtonBPs.png

    After deactivating the menu with the Play Game Button, we will be unable to do anything further in our game. This is the point at which we would normally load the first level, play an introductory cutscene, or spawn and possess a Pawn.

  9. We should now have two screens that look roughly as follows:

    FinalScreen.png

    FinalScreen2.png

6. On Your Own!

Using what you have learned, try to do the following:

  • Have multiple menus open at the same time.

  • Slide or fade Widgets onto the screen instead of just having them appear.

  • Look into the different sound, style, and color properties that Widgets support.

  • Set variables in your GameMode such as difficulty level, character class, and so on from within menus.

  • Create an in-game menu that pops up and pauses the game when the player presses a key, then resumes gameplay when it is closed.

  • Link any functionality you've built or learned from a previous tutorial to a menu built in Unreal Motion Graphics (UMG).

As for the specifics covered in this tutorial:

Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback