Quick answer: The most common cause is forgetting to call AddToViewport() after creating the widget with CreateWidget. Without AddToViewport, the widget exists in memory but is never added to the player's screen.

Here is how to fix Unreal UMG widget not showing on screen. You designed a beautiful HUD widget in the UMG editor, created it in C++ or Blueprints, and hit Play — but the screen is empty. No health bar, no score counter, no menu. The widget exists in memory (you can verify with breakpoints or print statements), but nothing renders on screen. This is one of the most common UMG issues and it usually comes down to a missing AddToViewport call or a visibility setting buried deep in the widget hierarchy.

The Symptom

You have a Widget Blueprint designed in the UMG editor with text blocks, images, progress bars, or other visual elements. In your character or HUD class, you call CreateWidget() and store the result in a variable. At runtime, the pointer is valid and not null, but nothing appears on screen. The game runs normally in the background with no UI overlay.

In some cases, the widget briefly flashes on screen and then disappears. In others, parts of the widget appear but key elements are missing. You might also see the widget in the editor preview but not at runtime, or it may appear during Play In Editor but not in a standalone build.

Another variant is that the widget appears but is positioned entirely off-screen, giving the impression that it was never created. This is especially common when anchors are misconfigured or when using absolute positioning with hardcoded pixel values that do not account for different screen resolutions.

What Causes This

1. AddToViewport was never called. This accounts for the majority of cases. CreateWidget() constructs the widget object in memory and runs its initialization logic, but it does not add the widget to the player’s viewport. You must explicitly call AddToViewport() on the widget instance. Without this call, the widget is fully constructed but never passed to the Slate rendering pipeline.

2. Visibility is set to Hidden or Collapsed. If the root widget or any critical parent panel in the widget hierarchy has its visibility set to ESlateVisibility::Hidden or ESlateVisibility::Collapsed, nothing beneath it will render. This can happen if a visibility binding returns the wrong value on construction, or if you set visibility to Hidden in the widget’s designer defaults.

3. ZOrder conflict with another widget. If another full-screen widget (such as a loading screen or fade overlay) has a higher ZOrder and is fully opaque, it will cover your widget completely. The widget is technically on screen but invisible behind the other layer.

4. Widget has zero size or invalid geometry. A widget with no content and no explicit size produces zero-area geometry. This happens when you create an empty CanvasPanel as the root with no children, or when size box constraints produce a degenerate layout. The widget is in the viewport but occupies zero pixels.

The Fix

Step 1: Create the widget and add it to the viewport. This is the correct minimal setup for displaying a UMG widget from C++.

// MyHUD.h
UPROPERTY(EditDefaultsOnly, Category = "UI")
TSubclassOf<UUserWidget> HUDWidgetClass;

UPROPERTY()
UUserWidget* HUDWidgetInstance;

// MyHUD.cpp - BeginPlay
void AMyHUD::BeginPlay()
{
    Super::BeginPlay();

    if (HUDWidgetClass)
    {
        HUDWidgetInstance = CreateWidget<UUserWidget>(
            GetOwningPlayerController(), HUDWidgetClass);

        if (HUDWidgetInstance)
        {
            // This is the critical call - without it, nothing renders
            HUDWidgetInstance->AddToViewport(0);

            UE_LOG(LogTemp, Warning, TEXT("Widget added to viewport"));
        }
    }
    else
    {
        UE_LOG(LogTemp, Error, TEXT("HUDWidgetClass is null!"));
    }
}

Step 2: Force visibility to Visible and diagnose hidden parents. Walk the widget hierarchy and ensure nothing is set to Hidden or Collapsed.

// Force the widget visible after adding to viewport
HUDWidgetInstance->SetVisibility(ESlateVisibility::SelfHitTestInvisible);

// Diagnostic: check visibility of the widget
ESlateVisibility Vis = HUDWidgetInstance->GetVisibility();
UE_LOG(LogTemp, Warning, TEXT("Widget visibility: %d"), (int)Vis);

// Check if the widget is actually in the viewport
bool bInViewport = HUDWidgetInstance->IsInViewport();
UE_LOG(LogTemp, Warning, TEXT("In viewport: %s"),
    bInViewport ? TEXT("true") : TEXT("false"));

Step 3: Handle ZOrder and ensure your widget is on top. If you suspect another widget is covering yours, set a higher ZOrder value.

// Add with explicit ZOrder (higher = more on top)
HUDWidgetInstance->AddToViewport(10);

// To remove and re-add with different ZOrder
if (HUDWidgetInstance->IsInViewport())
{
    HUDWidgetInstance->RemoveFromParent();
}
HUDWidgetInstance->AddToViewport(100);

// Set desired size to avoid zero-geometry issues
HUDWidgetInstance->SetDesiredSizeInViewport(
    FVector2D(1920.f, 1080.f));

Related Issues

If your widget shows up but does not respond to click or hover input, the issue is likely hit-test visibility — make sure interactive elements use Visible rather than SelfHitTestInvisible. If your character stops moving after the widget appears, check our guide on CharacterMovementComponent not working as input mode may have switched to UI Only. For particle effects that should appear alongside your HUD but do not render, see Niagara particles not spawning.

CreateWidget allocates. AddToViewport renders. You need both.