menus and submenus in UMG

I’ve been looking into getting a UMG menu system (including submenus) working with my game in C++. Each menu is represented by its own C++ class which inherits from UUserWidget and I’m handling the button OnClicked() functionality in C++. Then of course I create Blueprint classes based on these C++ menu classes.

The main problem that I have encountered so far is the back button on the submenus. On hitting back, we can remove the current submenu from viewport but then how does it know which menu we came from? If the submenu knows what type of menu we came from, it can create a new widget for the previous menu and add it to the viewport while removing itself.

Another option would be if the submenus fired off an event when they were closed that spawning menu listened for. Then the menu that created the submenu would know when it was closed and could set itself to be visible again. The problem with this is that every submenu type would need a custom OnClosed event and I’m wondering if this could get messy once a lot of submenus were added.

Looking at the Epic examples it seems like they all use Slate with some built in functionality from GameMenuBuilder which comes with the engine. I think that GameMenuBuilder is only designed to work with Slate and not UMG. As far as I know there is no equivalent system in place for building complex menu systems with UMG. But based on what I see, it looks like they keep some type of menu history for navigating between submenus:

    /** Stack of previous menus. */
    TArray< TSharedPtr< FGameMenuPage>> MenuHistory;

So I could try to keep some menu history like this but it would need to be in a place that all of the C++ menu classes could access. I don’t want to overcomplicate things by creating some complex menu handling system but it would be nice to have this basic type of submenu functionality without reinventing the wheel.

Anyone have any ideas on how the submenus are typically linked together like this in C++?

Last 2 projects we used a “Menu State stack” that lives in the PlayerController. Nothing too fancy and works well.

MenuState is a class with:

  • enum MenuStateType: “main menu”, “login”, “exit menu”, etc.
  • enum MenuStateSubType: additional info for the state type, if any
  • string AdditionInfo: this is used for example, in a generic Error popup, with the additional info being the error message

Your goal for the MenuState stack: whatever is showing on screen must be 100% recoverable from the data in the MenuState class item on top of the stack. The MenuState class does have OnEnter() and OnExit() events but aren’t used much.