Tutorial: a working multiplayer menu
Step 1: A menu on screen
Create the levels, the Game Mode, the Player Controller and the menu widget, and get the menu showing when you press Play.
No Steam in this step. It only gets a menu on screen, because you cannot test what you cannot see.
You will make four things: two levels, a Player Controller that creates the menu, a Game Mode that installs that controller, and the menu widget itself.
Create the two levels
- In the Content Browser, right click and choose Level. Name it
L_Menu. - Right click again, choose Level, and name it
L_Match. - Open
L_Match, put a floor and a light in it so it is visibly a different place, and save. - Open
L_Menuand leave it empty.
L_Match instead of making an empty one. It already has a floor, a Player Start and a Game Mode that spawns a character, which saves setting all three up later. An empty map still works, but players arrive in the dark with nothing under them, which looks exactly like a bug that is not there.Create the menu widget
- Right click in the Content Browser and choose User Interface > Widget Blueprint.
- Choose User Widget if it asks for a parent class.
- Name it
WBP_MainMenuand open it.
You are now in the UMG designer. Palette on the left lists what you can add, Hierarchy shows what you have added, and the middle is the canvas.
Two panels, not one list of buttons
A player is never doing all of this at once. Before they are in a session they can host or look for one. Once they are in, hosting and searching are meaningless and what they want is to see who else is here.
So the menu is two panels and you show one at a time:
| Panel | Shown when | Holds |
|---|---|---|
| Browse | Not in a session | Host, Find, the session list, Join |
| Lobby | In a session | The player list, Start, Leave |
Lay out the panels
- Drag a Vertical Box from the Palette onto the canvas. This is the root; both panels go inside it.
- Drag a second Vertical Box into the first. This is the Browse panel.
- Drag a third Vertical Box into the first, below the second. This is the Lobby panel.
Into the Browse panel:
- Two Button widgets, each with a Text widget inside, labelled Host and Find.
- A Combo Box (String) below them.
- One more Button with a Text inside, labelled Join.
Into the Lobby panel:
- A Text widget for the player list.
- Two Button widgets with Text inside, labelled Start and Leave.
Finally, drag one more Text widget into the root box, below both panels. That is your status line, and it belongs to neither panel because it has something to say in both.
Name them, and make them variables
This part matters. A widget you cannot reach from the graph is useless, and Unreal does not expose them by default.
Select each one in the Hierarchy, rename it in the Details panel, and tick Is Variable:
| Rename it to | What it is |
|---|---|
Panel_Browse | The first inner Vertical Box |
Panel_Lobby | The second inner Vertical Box |
Button_Host | The Host button |
Button_Find | The Find button |
Button_Join | The Join button |
Button_Start | The Start button |
Button_Leave | The Leave button |
Combo_Sessions | The Combo Box (String) |
Text_Players | The player list Text, in the Lobby panel |
Text_Status | The bottom Text widget |
Show the right panel
Two visibility bindings, and the menu switches itself. You never write code to swap them.
For Panel_Browse:
- Select it, and in Details find Behavior > Visibility. Click Bind, then Create Binding.
- Add Get SteamForge Sessions, drag off it to Is In Session.
- Add a Select node, feed the bool into Index, set True to
Collapsedand False toVisible, and wire it to Return Value.
For Panel_Lobby, do exactly the same but swap them: True is Visible, False is Collapsed.
Compile and save.
Create the Player Controller
The widget exists, but nothing creates it. A player's UI belongs to that player's Player Controller, so that is what creates it.
- Right click in the Content Browser and choose Blueprint Class.
- Pick Player Controller from the list.
- Name it
BP_MenuControllerand open it.
In its Event Graph, from Event BeginPlay:
- Create Widget, with its Class dropdown set to
WBP_MainMenu. - Drag off Return Value and add Add to Viewport.
- Add Set Input Mode UI Only, and connect the widget into its In Widget to Focus pin.
- Add Set Show Mouse Cursor, with its checkbox ticked.
Set Input Mode UI Only needs a Player Controller on its Target pin. Drag in a Self node, because inside a Player Controller you already are one. Set Show Mouse Cursor is a variable on this class, so it needs no target at all.
Compile and save.
Create the Game Mode
A Player Controller is not used until something says to use it. That is the Game Mode's job: it decides which Controller and which Pawn a level gets.
- Right click in the Content Browser and choose Blueprint Class.
- Pick Game Mode Base.
- Name it
BP_MenuGameModeand open it. - In the Details panel, find Classes and set Player Controller Class to
BP_MenuController.
Compile and save.
Tell the level to use it
- Open
L_Menu. - In the toolbar choose Window > World Settings.
- Set GameMode Override to
BP_MenuGameMode. - Save the level.
Check it
Press Play. You should see the Browse panel only: Host, Find, a dropdown, Join, and the status line. The Lobby panel is collapsed because you are not in a session, which is the bindings already doing their job.
The buttons do nothing yet. That comes next.
If you see nothing at all, confirm you are playing L_Menu and that its GameMode Override is set. If you see both panels, one of the two Select nodes has True and False the wrong way round.