Make ShowHUD actually show and hide your UMG HUD

Unreal has a console command "ShowHUD" which is supposed to toggle HUD visibility, but it's extremely legacy and only hides things that are drawn via code from the HUD, not your UMG Widgets.

This gist is a base class AHUD class that does the following

  1. Intercepts the ShowHUD command and toggles visibility of all of your UI
  2. Optionally hides the hid when you switch to simulate in PIE (Hit F8)

Main principle at work is to find the SPlayerLayer Widget, which is the root of all the UMG widgets you add to the player screen:

Overview of the main code, for reference. Full code in [the gist]

namespace RTMHUDBaseStatics
	SWidget* FindWidgetByTypeRecursive(SWidget* root, FName widgetType)
		SWidget* ret = nullptr;
		root->GetChildren()->ForEachWidget([widgetType, &ret](SWidget& child)
				if(child.GetType() == widgetType)
					ret = &child;
					ret = FindWidgetByTypeRecursive(&child, widgetType);

		return ret;

void ARTMHUDBase::UpdateUIVisibility()
	const bool wantVisible = bShowHUD && !(bHideUIDuringSimulate && IsSimulatingInEditor());
	const EVisibility visibility = wantVisible ? EVisibility::SelfHitTestInvisible : EVisibility::Hidden;
	if(auto* playerLayerWidget = GetPlayerLayerWidget())

SWidget* ARTMHUDBase::GetPlayerLayerWidget() const
	const FName playerLayer("SPlayerLayer");

	// TODO - investigate if this works for local multiplayer, as it's unclear if this will find the Player Layer for this player, or the first one it finds
	const ULocalPlayer* localPlayer = Cast<ULocalPlayer>(PlayerOwner->Player);
	const UGameViewportClient* viewportClient = localPlayer ? localPlayer->ViewportClient.Get() : nullptr;
	auto viewportWidget = viewportClient ? viewportClient->GetGameViewportWidget() : TSharedPtr<SViewport>();

	return viewportWidget.IsValid() ? RTMHUDBaseStatics::FindWidgetByTypeRecursive(viewportWidget.Get(), playerLayer) : nullptr;