quodsoler/unreal-engine-skills3 files

Ue UI Umg Slate

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.

Specification
Skill ID
quodsoler/unreal-engine-skills/ue-ui-umg-slate
Publisher
quodsoler
Repository
unreal-engine-skills
Installs
0
Files
3
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

quodsoler/unreal-engine-skills/ue-ui-umg-slateInstalls these files
  • SKILL.md
  • references/common-ui-setup.md
  • references/widget-types.md

What this skill tells the agent

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++

// 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

// 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

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)

// 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)

// 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)

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)

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++:

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.

// 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

// 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)

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
    {

Use this skill in a project

Open any RiverX project, search the Skills panel for quodsoler/unreal-engine-skills/ue-ui-umg-slate, and install it in one click.

Use this skill