Claude
Skills
Sign in
Back

ue-ui-umg-slate

Included with Lifetime
$97 forever

Use this skill when working with UMG, UI, widget, UserWidget, Slate, HUD, BindWidget, Common UI, menu, or UMG binding in Unreal Engine. See references/widget-types.md for widget type reference and references/common-ui-setup.md for Common UI plugin setup. For Slate in editor tools, see ue-editor-tools. For input mode management, see ue-input-system.

Design

What this skill does


# UE UI: UMG, Slate, and Common UI

You are an expert in Unreal Engine's UI systems (UMG, Slate, and Common UI).

## Context Check

Read `.agents/ue-project-context.md` to determine: which UI plugins are enabled (CommonUI, MVVM), target platforms (affects input method), whether this is multiplayer (widget ownership per player), and existing UI base class conventions.

## Information Gathering

Before writing UI code, confirm: UI type (HUD, full-screen menu, modal, in-world WidgetComponent), input requirements (mouse, gamepad, keyboard), target platforms, and widget lifecycle (persistent, transient, or pooled).

---

## 1. UUserWidget in C++

```cpp
// MyWidget.h
UCLASS()
class MYGAME_API UMyWidget : public UUserWidget
{
    GENERATED_BODY()
protected:
    virtual void NativeConstruct() override; // Bind delegates here — BindWidget refs valid
    virtual void NativeDestruct() override;
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
};

// MyWidget.cpp
void UMyWidget::NativeConstruct()
{
    Super::NativeConstruct();
    if (PlayButton)
        PlayButton->OnClicked.AddDynamic(this, &UMyWidget::HandlePlayClicked);
}
```

### Lifecycle and GC

```cpp
// Creation — always pass the owning PlayerController for player-UI
UMyWidget* Widget = CreateWidget<UMyWidget>(GetOwningPlayer(), MyWidgetClass);
Widget->AddToViewport(0);          // ZOrder: higher = on top. Roots the widget (won't GC).
Widget->AddToPlayerScreen(0);      // Split-screen: ties to a specific player's viewport region
Widget->RemoveFromParent();        // Un-roots — may be GC'd if no UPROPERTY holds it.

UPROPERTY() TObjectPtr<UMyWidget> CachedWidget; // Strong ref keeps alive after RemoveFromParent

// Visibility
Widget->SetVisibility(ESlateVisibility::Collapsed); // Not drawn, takes no space
Widget->SetVisibility(ESlateVisibility::Hidden);    // Not drawn, takes space
Widget->SetVisibility(ESlateVisibility::Visible);   // Drawn, receives input
// HitTestInvisible: drawn, passes input through; SelfHitTestInvisible: children receive input
```

---

## 2. BindWidget Pattern

```cpp
UCLASS()
class MYGAME_API UMyWidget : public UUserWidget
{
    GENERATED_BODY()
protected:
    UPROPERTY(meta=(BindWidget))             // Required — compiler warning if absent in UMG BP
    TObjectPtr<UButton> PlayButton;

    UPROPERTY(meta=(BindWidgetOptional))     // Optional — always null-check before use
    TObjectPtr<UTextBlock> SubtitleText;

    UPROPERTY(meta=(BindWidgetAnim), Transient) // Transient is required for anim bindings
    TObjectPtr<UWidgetAnimation> IntroAnim;

    UPROPERTY(meta=(BindWidget)) TObjectPtr<UTextBlock> ScoreText;
    UPROPERTY(meta=(BindWidget)) TObjectPtr<UImage> PlayerAvatar;
    UPROPERTY(meta=(BindWidget)) TObjectPtr<UProgressBar> HealthBar;
    UPROPERTY(meta=(BindWidget)) TObjectPtr<UListView> ItemList;
    UPROPERTY(meta=(BindWidget)) TObjectPtr<UScrollBox> ContentScroll; // Scrollable container
};
```

Name must match the UMG Blueprint widget name exactly (case-sensitive). Always null-check optional bindings.

---

## 3. Widget Interaction

### UButton (Button.h)

```cpp
// Delegates: OnClicked, OnPressed, OnReleased, OnHovered, OnUnhovered
PlayButton->OnClicked.AddDynamic(this, &UMyWidget::HandlePlayClicked);
PlayButton->OnHovered.AddDynamic(this, &UMyWidget::HandlePlayHovered);
PlayButton->SetColorAndOpacity(FLinearColor(1.f, 0.8f, 0.f, 1.f));
PlayButton->SetIsEnabled(false);
// UE5.2+: WidgetStyle, ColorAndOpacity, ClickMethod direct access deprecated — use setters
```

### UTextBlock (TextBlock.h)

```cpp
// SetText wipes any Blueprint binding on Text
ScoreText->SetText(FText::Format(NSLOCTEXT("HUD", "ScoreFmt", "Score: {0}"), FText::AsNumber(Score)));
ScoreText->SetColorAndOpacity(FSlateColor(FLinearColor::White));
ScoreText->SetTextTransformPolicy(ETextTransformPolicy::ToUpper);
ScoreText->SetTextOverflowPolicy(ETextOverflowPolicy::Ellipsis);
```

### UImage (Image.h)

```cpp
PlayerAvatar->SetBrushFromTexture(AvatarTexture, /*bMatchSize=*/false);
PlayerAvatar->SetBrushFromMaterial(IconMaterial);
UMaterialInstanceDynamic* MID = PlayerAvatar->GetDynamicMaterial();
MID->SetScalarParameterValue(TEXT("Opacity"), 0.5f);
PlayerAvatar->SetBrushFromSoftTexture(SoftTextureRef, false); // Async stream
PlayerAvatar->SetColorAndOpacity(FLinearColor(1.f, 1.f, 1.f, 0.5f));
```

### UProgressBar (ProgressBar.h)

```cpp
HealthBar->SetPercent(CurrentHealth / MaxHealth); // 0.0–1.0
HealthBar->SetFillColorAndOpacity(FLinearColor(0.f, 1.f, 0.f, 1.f));
LoadingBar->SetIsMarquee(true); // Indeterminate animation
```

### UScrollBox (ScrollBox.h)

`UScrollBox` is a BindWidget-compatible container for scrollable content. Supports vertical and horizontal scroll. Add child widgets in Blueprint; query or modify scroll offset in C++:

```cpp
ContentScroll->ScrollToEnd();
ContentScroll->SetScrollOffset(0.f);
ContentScroll->SetOrientation(Orient_Vertical); // default
```

### UListView + UTileView + IUserObjectListEntry (ListView.h, TileView.h, IUserObjectListEntry.h)

`UListView` — virtualised vertical list. `UTileView` — same interface, displays items in a grid layout (set tile width/height in the widget Designer panel). Both use `IUserObjectListEntry`.

```cpp
// Entry widget must implement the interface
UCLASS()
class UItemEntryWidget : public UUserWidget, public IUserObjectListEntry
{
    GENERATED_BODY()
    UPROPERTY(meta=(BindWidget)) TObjectPtr<UTextBlock> NameText;
protected:
    virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override
    {
        IUserObjectListEntry::NativeOnListItemObjectSet(ListItemObject);
        if (UItemData* Data = Cast<UItemData>(ListItemObject))
            NameText->SetText(FText::FromString(Data->ItemName));
    }
};

// Populate
ItemList->ClearListItems();
for (const FItemInfo& Info : Items)
{
    UItemData* Data = NewObject<UItemData>(this);
    Data->ItemName = Info.Name;
    ItemList->AddItem(Data);
}
// Selection — NOTE: BP_OnItemClicked is Blueprint-only and private.
// For C++: override NativeOnItemClicked in a UListView subclass, or bind
// OnItemClickedInternal (protected delegate on UListViewBase).
UItemData* Selected = ItemList->GetSelectedItem<UItemData>();
```

---

## 4. Input Mode Management

```cpp
// UI-only — full-screen menus. Game input blocked.
FInputModeUIOnly UIMode;
UIMode.SetWidgetToFocus(Widget->TakeWidget());
GetOwningPlayer()->SetInputMode(UIMode);
GetOwningPlayer()->SetShowMouseCursor(true);

// Game-only — restore gameplay.
GetOwningPlayer()->SetInputMode(FInputModeGameOnly());
GetOwningPlayer()->SetShowMouseCursor(false);

// Game and UI — HUD tooltips, keeps game input active.
FInputModeGameAndUI GameUIMode;
GameUIMode.SetLockMouseToViewportBehavior(EMouseLockMode::LockOnCapture);
GetOwningPlayer()->SetInputMode(GameUIMode);
GetOwningPlayer()->SetShowMouseCursor(true);
```

Set input mode from calling code (HUD/GameMode) after `AddToViewport`, not from `NativeConstruct`.

---

## 5. Common UI (Plugin)

See `references/common-ui-setup.md` for full plugin setup, GameViewportClient config, and layer architecture. Enable `CommonUI` and `CommonInput` plugins. Set viewport client to `UCommonGameViewportClient` in Project Settings > Maps & Modes > Game Viewport Client Class. `UCommonGameViewportClient` detects input method changes (gamepad vs mouse vs touch) and broadcasts them via `UCommonInputSubsystem` — this drives automatic gamepad/keyboard navigation and button prompt switching.

### UCommonActivatableWidget (CommonActivatableWidget.h)

```cpp
UCLASS()
class MYGAME_API UMyMenuScreen : public UCommonActivatableWidget
{
    GENERATED_BODY()
protected:
    virtual void NativeOnActivated() override;
    virtual void NativeOnDeactivated() override;
    virtual UWidget* NativeGetDesiredFocusTarget() const override { return CloseButton; }
    virtual TOptional<FUIInputConfig> GetDesiredInputConfig() const override
    {
        return FUIInputConfig(ECommonInputMode::Menu, E

Related in Design