Making a Main Menu Widget
We have a Hero, with animations and movement, and a world for him to walk around in. For a game to have a beginning and an end, however, there needs to be an entry and exit for the player to start and stop.
It's time to dive into Unreal Engine's widgets.
Our First Widget
In the content browser right click and go to User Interface > Widget Blueprint. This will make a new widget, which you should name. I use "WB_" as my prefix for Widget Blueprints. This one will be called "WB_MainMenu".
Creating a Widget Blueprint. |
Double-click and open up the Widget Blueprint editor.
This is kind of like playing around in Photoshop now, if you've ever done that. Or any image editing software. We'll be using layers and a hierarchy to manipulate and stitch together images on the screen that can be buttons, text, images or colors, and also organizational tools.
On the left you'll see the Hierarchy tab. It shows currently just the name of your Widget Blueprint and something called "Canvas Panel" under it. That's our canvas which will be the parent of our buttons and texts we want for our menu.
Above that tab—if your windows are all default—there will be a Palette tab. This holds all the available things we can drag into our widget or hierarchy and use.
Go ahead and open up the "Common" category and drag a "Border" either into the viewer or onto the "Canvas Panel" in the hierarchy tree.
A border can be a color or an image and is allowed to have a single child. This is going to become the main menu with buttons of Play, Load (eventually), Options, and Quit. On the right side you'll see our familiar Details tab.
The first thing you want to do is change the Anchor. This tells the game how to render the widget if the resolution is modified. The reality is that not everyone plays at the same resolution, so an anchor gives a reference point and everything is scaled. For our border we just want it stretched corner to corner to fill the screen at any resolution. Click the Anchors button to see all the options and select the lower right.
Anchor options. |
Once you've changed the Anchor, this will also adjust some of your options for the Details. Specifically you'll now see Offset options instead of Position and Size. Make sure all your offsets are set to 0 to get the Border to fill the whole widget canvas.
Then, under the Content tab of your Details change the Horizontal and Vertical Alignment to be centered, so that the child of the Border will be right in the middle of it.
Go to the Appearance tab next, below Content, and change the Brush Color to whatever you'd like. You should see the Border change color.
The next thing we want to use is a "Vertical Box". This is under the "Panel" category in the Palette. This, and the "Horizontal Box", behave as organizers that will keep child objects aligned. As you add text or buttons to one of these boxes they'll be stacked and kept neat.
Click and drag a Vertical Box onto your Border in the Hierarchy to child it. The Vertical and Horizontal Alignment should match what we set in the Content tab for the Border, but if it doesn't, make sure those are set to centered.
What we want to put into this Vertical Box are now our buttons and a game title.
Our menu hierarchy of buttons and text. |
Drag a "Text" from the Palette under the Common category. Then drag in four buttons, also from Common, and give each of those buttons their own Text. Match up your hierarchy so it resembles my image above.
Give them names and change the colors of things as you wish. If you have any custom fonts, feel free to use them.
Make Buttons Do Button-Things
We now want to make our buttons do button-things. Select one of your buttons and scroll to the very bottom of the Details panel. You'll find the Events section.
Button-Things |
These are pretty self-explanatory. Hit the plus-sign next to "On Clicked" for your button.
We're now back in familiar territory with nodes and pipelines. Just like any other Blueprint in Unreal, Widgets also behave based on an Event Graph. Pretty cool!
You now have a red event: "On Clicked (name of your button)". This will fire off its execution pin when the specified button—in my case, my PlayButton—is clicked.
I want my PlayButton to load our game. To do that, it needs to execute the "Open Level" node. Right click and search for that, then connect the pins. My level is named "TestMap" so I put that literal into the node's "Level Name" option.
Just play the game. |
This is a super basic example of what you can do with a button.
We'll also do something simple for our quit button. Go ahead and give that an "On Clicked" event as well, and then connect it to an "Execute Console Command" node. The command we want? Easy: quit.
And quit the game. |
We'll ignore the Load button for now. Saving and Loading will be a big subject for another time. But let's make our Options menu.
Options, Options, Options
We're going to give our player a few window resolutions, should they not be in fullscreen mode.
Hide your MainMenuBorder by hitting the little eye icon to the right of it in the Hierarchy.
Make another Border and child it to the Canvas Panel again. Repeat similar steps to make buttons and text.
Options hierarchy tree. |
These won't do anything in fullscreen mode, so I put a little extra text hint at the bottom for now that clarifies these buttons are "for windowed resolutions".
Make sure you name your buttons and set your text up. Choose colors and other things to your liking. Once done, give each of those buttons a click event, along with the Options button from the main menu buttons.
We have to swap visibility between these two menus. This is really simple. We need our borders to be variables. In the Details panel, with the MainMenuBorder selected (or whatever you named it) check the "is variable" box at the very top next to the name.
Is Variable? |
That's it. It's now accessible in the Event Graph. Head back over there and let's make our buttons do button-things.
When we click on the Options Button we want our Main Menu to hide and our Options Menu to appear. So off the execution pin of "On Clicked (OptionsButton)" send it to a "Set Visibility" node. Ctrl-Click and Drag your "MainMenuBorder" variable out from the familiar Variables section on the left and hook it up as the "Target". Change the "In Visibility" setting to Hidden in the dropdown.
Next, hook up another "Set Visibility" and this time make the Target the "OptionsBorder". Set its visibility to "Visible".
For each of the "On Clicked" events for your settings buttons, you want to execute a console command again, just like we did for Quit. This time the console commands will be "r.setRes VALUExVALUE". I'm going to offer 640x480, 1280x720, and 1920x1080 just for debug purposes.
Then, do the reverse for visibility for the Return. Make the OptionsBorder "Hidden" and the MainMenuBorder "Visible".
Here's how my graph looks.
Options Menu Event Graph. |
The last thing I'd recommend is make an "Event Construct" node that sets the visibility of your MainMenuBorder to Visible and the OptionsBorder to Hidden so that when the menu is created it shows the player the Main Menu by default. Just in case wires get crossed.
Now Use It
So we've got the Widget. Now what? Well, we need to now use it. And in order to do that we have to make a level dedicated to our menu.
Right click in the content browser and make a new Level. Name it "Main" or something that makes sense.
To get access to a level's Blueprint, you need to go to "Blueprints" above the editor viewport and select "Open Level Blueprint".
How to get a level's Blueprint. |
With the level's Event Graph open, create an "Event BeginPlay" if there isn't one already. We want to do two primary things: disable input, to prevent key presses that might be used in the game eventually; and create the Main Menu Widget we just made.
I like to use a "Sequence" node to keep things neat and orderly if I have things I want to fire off, one after another.
Here's how my Event Graph looks for my "Main" level.
Use a "Get Player Controller" to find that "Set Show Mouse Cursor" node. Check the box.
Then send the Player Controller and the Widget into a final "Set Input Mode Game and UI" node. You can play with the "In Mouse Lock Mode" options if you want to.
The final step is to set focus to our game once the game level is loaded.
Open up the TestMap level—or your primary game level that will be loaded when we hit Play—and open that level's Blueprint.
In the Event Graph make another "Event BeginPlay". Send it to a "Set Focus to Game Viewport".
That's it. Pretty easy. Now the player won't have to click on the game window to set focus when it loads the level. The mouse will automatically disappear and we'll be in the game, controlling our Hero.
NOTE: I originally had "Enable Input" here as well, but after testing I discovered that Unreal Engine seems to enable input by default when a level is loaded. I believe this is because everything except the Game Instance is destroyed and recreated between level changes, so our defaults get flipped back and we have input again. So no need to worry about this!
For your game to load into the Main Menu when it launches, go to Project Settings, and under Projects, go to Maps & Modes and change the "Game Default Map" to Main (or what you named your level which will spawn the MainMenu Widget). I keep my "Editor Startup Map" to my TestMap, because that's where I'm working usually.
The defaults for what your game or editor will load on startup. |
That wraps up how to make a Main Menu for our game. Next time we'll make the in-game menu that allows us to Resume, Save, and Quit!
- Matthew
Comments
Post a Comment