All skills
quodsoler avatar

/ue-ui-umg-slate

@f3742d7

Use when writing or fixing Unreal Engine UI in C++ — UMG user widgets, Slate widgets, Common UI screens, or MVVM view models. Also use when the user mentions 'UUserWidget', 'NativeConstruct', 'BindWidget', 'CreateWidget', 'AddToViewport', 'ESlateVisibility', 'OnClicked', 'UListView', 'widget animation', 'SNew', 'SLATE_BEGIN_ARGS', 'SCompoundWidget', 'UCommonActivatableWidget', 'activatable widget stack', 'UCommonButtonBase', 'gamepad focus', 'FUIInputConfig', 'UMVVMViewModelBase', 'FieldNotify', or 'WidgetComponent'. For input modes and Enhanced Input, see ue-input-system; for Slate in editor tooling, see ue-editor-tools.

Use this Skill: https://skilld.dev/gh/quodsoler/unreal-engine-skills/ue-ui-umg-slate

This session only. Nothing lands on disk.

SKILL.md

≈162 tokens always: the name and description. ≈7.3k when used: this file. ≈14k more on demand in 3 files.

UE UI: UMG, Slate, and Common UI

Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".

UMG is the runtime UI framework (UMG module, Engine/Source/Runtime/UMG/Public) built on Slate (Slate, SlateCore). Common UI (plugin, production in 5.8) adds cross-platform input routing, activation stacks and platform-aware buttons. Model View Viewmodel (plugin, Beta in 5.8) adds declarative data binding on top of FieldNotification.

Context

Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.

Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.

Request is about… Go to
Widget class, overrides, creation, visibility, GC Widget Lifecycle
Wiring designer widgets into C++ (meta=(BindWidget)) BindWidget
Buttons, text, images, bars, lists Widget Interaction
Playing/stopping UMG animations Widget Animation
Mouse cursor, focus, SetInputMode Input Mode and Focus
Menus, screen stacks, gamepad, back action Common UI
Data binding, view models, field notifications MVVM
UI rendered in the level World-Space UI
Iterating widgets, drag/drop, brushes, geometry Widget Tree and Helper Libraries
Custom SWidget, SNew, SLATE_BEGIN_ARGS Slate

Per-widget method tables (setters, delegates, enums) live in references/widget-types.md. Full Common UI plugin setup lives in references/common-ui-setup.md. A complete custom Slate widget lives in references/slate-patterns.md.

Widget Lifecycle

// MyWidget.h
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "MyWidget.generated.h"

class UButton;

UCLASS()
class MYGAME_API UMyWidget : public UUserWidget
{
    GENERATED_BODY()

protected:
    virtual void NativeOnInitialized() override;
    virtual void NativePreConstruct() override;
    virtual void NativeConstruct() override;
    virtual void NativeDestruct() override;
    virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;

    UPROPERTY(meta=(BindWidget))
    TObjectPtr<UButton> PlayButton;

    UFUNCTION()
    void HandlePlayClicked();
};

// MyWidget.cpp — #include "MyWidget.h" and "Components/Button.h"
void UMyWidget::NativeOnInitialized() { Super::NativeOnInitialized(); }
void UMyWidget::NativePreConstruct() { Super::NativePreConstruct(); }
void UMyWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
    Super::NativeTick(MyGeometry, InDeltaTime);
}

void UMyWidget::NativeConstruct()
{
    Super::NativeConstruct();       // Runs on every re-add; pair each bind with an unbind in NativeDestruct
    PlayButton->OnClicked.AddDynamic(this, &UMyWidget::HandlePlayClicked);
}

void UMyWidget::NativeDestruct()
{
    PlayButton->OnClicked.RemoveDynamic(this, &UMyWidget::HandlePlayClicked);
    Super::NativeDestruct();
}
Override (verbatim from Blueprint/UserWidget.h) When it runs
virtual void NativeOnInitialized() override; Once per instance, after construction of the widget object
virtual void NativePreConstruct() override; After the Slate tree is rebuilt, just before NativeConstruct (UserWidget.cpp:1231); also runs in the Designer
virtual void NativeConstruct() override; Slate widget added to a parent — bind delegates here
virtual void NativeDestruct() override; Slate widget removed — unbind here
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; Per frame while ticking
virtual int32 NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; Custom drawing; return the last used layer id
virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; Pointer press
virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override; Key press while focused
virtual FReply NativeOnFocusReceived(const FGeometry& InGeometry, const FFocusEvent& InFocusEvent) override; This widget gained focus
virtual void NativeOnAddedToFocusPath(const FFocusEvent& InFocusEvent) override; This widget or a descendant gained focus
virtual bool Initialize() override; Builds the widget tree; call Super::Initialize() and return its result
virtual TSharedRef<SWidget> RebuildWidget() override; Builds the underlying Slate widget
virtual void ReleaseSlateResources(bool bReleaseChildren) override; Drop cached TSharedPtr<SWidget> members here

Input handlers return FReply::Handled() to consume the event or FReply::Unhandled() to let it bubble.

Creation, viewport, visibility

// CreateWidget<T>(Owner, Class, WidgetName = NAME_None). Owner may be a UWidget,
// UWidgetTree, APlayerController, UGameInstance or UWorld.
UMyWidget* Widget = CreateWidget<UMyWidget>(GetOwningPlayer(), MyWidgetClass);
Widget->AddToViewport(0);       // ZOrder: higher draws on top. Roots the widget.
Widget->AddToPlayerScreen(0);   // Split-screen: one player's viewport region; returns bool
Widget->RemoveFromParent();     // Un-roots - collectable unless a UPROPERTY holds it
Widget->SetVisibility(ESlateVisibility::Collapsed);  // Not drawn, takes no space
Widget->SetVisibility(ESlateVisibility::Hidden);     // Not drawn, still takes space
Widget->SetVisibility(ESlateVisibility::Visible);    // Drawn, hit-testable
Widget->SetIsEnabled(false);                         // Greys out, blocks input

HitTestInvisible draws but passes input through for the widget and its children; SelfHitTestInvisible passes input through for the widget only. Hold a UPROPERTY() TObjectPtr<UMyWidget> if the widget must survive RemoveFromParent. GetOwningPlayer() returns the owning APlayerController; GetOwningPlayer<AMyPlayerController>() casts for you.

BindWidget

UPROPERTY(meta=(BindWidget))                 // Compile error in the Widget BP if missing
TObjectPtr<UTextBlock> ScoreText;
UPROPERTY(meta=(BindWidgetOptional))         // May be null - always null-check
TObjectPtr<UTextBlock> SubtitleText;
UPROPERTY(Transient, meta=(BindWidgetAnim))  // Transient is required for animation bindings
TObjectPtr<UWidgetAnimation> IntroAnim;

Rules: the C++ member name must match the Widget Blueprint's widget name exactly (case-sensitive); the declared type must match or be a base of the designer widget's class; bound members are assigned inside Initialize() before NativeOnInitialized runs (UserWidget.cpp:153,175), so they are valid in NativeOnInitialized, NativePreConstruct and NativeConstruct — bind once-per-instance delegates in NativeOnInitialized. Declare them protected with no Category.

Widget Interaction

Dynamic multicast delegates on UMG components use AddDynamic, so the handler must be a UFUNCTION().

PlayButton->OnClicked.AddDynamic(this, &UMyWidget::HandlePlayClicked);
PlayButton->SetColorAndOpacity(FLinearColor(1.f, 0.8f, 0.f, 1.f));
ScoreText->SetText(FText::Format(NSLOCTEXT("HUD", "ScoreFmt", "Score: {0}"), FText::AsNumber(Score)));
ScoreText->SetTextOverflowPolicy(ETextOverflowPolicy::Ellipsis);
PlayerAvatar->SetBrushFromSoftTexture(SoftAvatarTexture, /*bMatchSize=*/false);
UMaterialInstanceDynamic* AvatarMID = PlayerAvatar->GetDynamicMaterial();
AvatarMID->SetScalarParameterValue(TEXT("Opacity"), 0.5f);
HealthBar->SetPercent(CurrentHealth / MaxHealth);   // 0.0-1.0
HealthBar->SetFillColorAndOpacity(FLinearColor(0.f, 1.f, 0.f, 1.f));

Method and enum tables for UButton, UTextBlock, UImage, UProgressBar, UScrollBox, UWidgetSwitcher, UCheckBox, UEditableTextBox, USlider, UComboBoxString and the UWidget base are in references/widget-types.md.

Lists: UListView, UTileView, UTreeView

All three are virtualised — only visible entry widgets exist, and they are recycled. Items are UObject*; the entry widget derives from UUserWidget and implements IUserObjectListEntry, overriding virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override; (call IUserObjectListEntry::NativeOnListItemObjectSet first). The full entry-widget example and the UListView method table are in references/widget-types.md.

ItemList->ClearListItems();
for (const FMyItemInfo& Info : Items)
{
    UMyItemData* Data = NewObject<UMyItemData>(this);
    Data->DisplayName = Info.DisplayName;
    ItemList->AddItem(Data);
}
UMyItemData* Selected = ItemList->GetSelectedItem<UMyItemData>();

BP_OnItemClicked is a Blueprint-only private delegate. From C++, bind the native event ItemList->OnItemClicked().AddUObject(...) (FSimpleListItemEvent, Components/ListViewBase.h:48; also OnItemSelectionChanged()), or override virtual void OnItemClickedInternal(UObject* Item) override; in a UListView subclass. Inside an entry widget, read the item with GetListItem<UMyItemData>() and query selection with the interface member IsListItemSelected() (Blueprint/IUserListEntry.h:32).

Widget Animation

PlayAnimation and its variants return an FWidgetAnimationHandle (Animation/WidgetAnimationHandle.h); keep the handle, not a sequence-player pointer. A valid handle may still resolve to no state once the animation finishes, so check IsValid().

// PlayAnimation(UWidgetAnimation*, StartAtTime=0, NumLoopsToPlay=1,
//               EUMGSequencePlayMode::Type=Forward, PlaybackSpeed=1, bRestoreState=false)
FWidgetAnimationHandle IntroHandle = PlayAnimation(IntroAnim);
IntroHandle.SetUserTag(TEXT("Intro"));
PlayAnimationForward(IntroAnim);                        // also PlayAnimationReverse
const float PausedAt = PauseAnimation(IntroAnim);
const bool bPlaying = IsAnimationPlaying(IntroAnim);
StopAnimation(IntroAnim);

Input Mode and Focus

ue-input-system owns input modes and Enhanced Input. Minimal correct form:

FInputModeUIOnly UIMode;
UIMode.SetWidgetToFocus(Widget->TakeWidget());
UIMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
GetOwningPlayer()->SetInputMode(UIMode);
GetOwningPlayer()->SetShowMouseCursor(true);
// Restore gameplay:
GetOwningPlayer()->SetInputMode(FInputModeGameOnly());
GetOwningPlayer()->SetShowMouseCursor(false);

FInputModeGameAndUI also has SetWidgetToFocus and SetLockMouseToViewportBehavior. Set the input mode from the code that added the widget (HUD, PlayerController, GameMode), not from NativeConstruct. When Common UI is enabled, do not call SetInputMode at all — return an FUIInputConfig instead.

Common UI

Enable the CommonUI plugin (it ships both the CommonUI and CommonInput modules), add both modules to Build.cs, and set the viewport client class to UCommonGameViewportClient — it reroutes input to the UI action router before the game (CommonGameViewportClient.h:21); gamepad/mouse/touch changes are detected by UCommonInputSubsystem's FCommonInputPreprocessor and broadcast from that subsystem. Setup details, layer architecture and settings keys are in references/common-ui-setup.md.

// MyMenuScreen.h
#pragma once
#include "CommonActivatableWidget.h"
#include "MyMenuScreen.generated.h"

class UCommonButtonBase;

UCLASS()
class MYGAME_API UMyMenuScreen : public UCommonActivatableWidget
{
    GENERATED_BODY()

protected:
    virtual void NativeOnActivated() override;
    virtual void NativeOnDeactivated() override;
    virtual UWidget* NativeGetDesiredFocusTarget() const override;
    virtual TOptional<FUIInputConfig> GetDesiredInputConfig() const override;
    virtual bool NativeOnHandleBackAction() override;   // Return true when handled

    UPROPERTY(meta=(BindWidget))
    TObjectPtr<UCommonButtonBase> CloseButton;

    void HandleCloseClicked();
};

// MyMenuScreen.cpp — #include "MyMenuScreen.h" and "CommonButtonBase.h"
void UMyMenuScreen::NativeOnActivated()
{
    Super::NativeOnActivated();     // Broadcasts OnActivated(), which activates this widget's tree node
    CloseButton->OnClicked().AddUObject(this, &UMyMenuScreen::HandleCloseClicked);
}

void UMyMenuScreen::NativeOnDeactivated()
{
    CloseButton->OnClicked().RemoveAll(this);
    Super::NativeOnDeactivated();   // Broadcasts OnDeactivated(); the router moves focus to the parent
}

UWidget* UMyMenuScreen::NativeGetDesiredFocusTarget() const { return CloseButton; }

TOptional<FUIInputConfig> UMyMenuScreen::GetDesiredInputConfig() const
{
    return FUIInputConfig(ECommonInputMode::Menu, EMouseCaptureMode::NoCapture);
}

bool UMyMenuScreen::NativeOnHandleBackAction() { DeactivateWidget(); return true; }
void UMyMenuScreen::HandleCloseClicked() { DeactivateWidget(); }

Public API: ActivateWidget(), DeactivateWidget(), IsActivated(), GetDesiredFocusTarget(), ClearFocusRestorationTarget(), RequestRefreshFocus(), plus the non-dynamic OnActivated() / OnDeactivated() delegates. BP_GetDesiredFocusTarget is the BlueprintImplementableEvent that NativeGetDesiredFocusTarget routes to — override the native one in C++. Editable defaults: bAutoActivate, bIsBackHandler, bIsBackActionDisplayedInActionBar, bIsModal, bAutoRestoreFocus, bSetVisibilityOnActivated/ActivatedVisibility, bSetVisibilityOnDeactivated/DeactivatedVisibility. ECommonInputMode is Menu (UI only), Game (game only) or All.

Containers

UCommonActivatableWidgetContainerBase (Widgets/CommonActivatableWidgetContainer.h) is the base; UCommonActivatableWidgetStack shows the topmost widget and re-activates the one beneath when it deactivates; UCommonActivatableWidgetQueue shows one at a time and advances when the active one deactivates. UCommonActivatableWidgetSwitcher is an index-based switcher, not a stack — do not use it here.

UPROPERTY(meta=(BindWidget))
TObjectPtr<UCommonActivatableWidgetStack> MenuLayer;
// AddWidget<T> creates (or pools) the instance, adds it, and the container activates it.
UMyMenuScreen* Screen = MenuLayer->AddWidget<UMyMenuScreen>(UMyMenuScreen::StaticClass());
// Overload with an init lambda that runs after creation, before the widget is added:
MenuLayer->AddWidget<UMyMenuScreen>(UMyMenuScreen::StaticClass(),
    [](UMyMenuScreen& Instance) { Instance.SetIsEnabled(true); });

if (UCommonActivatableWidget* Active = MenuLayer->GetActiveWidget())
{
    Active->DeactivateWidget();         // Pops the stack
}
// RemoveWidget(UCommonActivatableWidget&) deactivates the active widget, or yanks an inactive one
MenuLayer->RemoveWidget(*Screen);
MenuLayer->ClearWidgets();              // GetNumWidgets() reports the current depth

Buttons, input type, action routing

// UCommonButtonBase::OnClicked() returns FCommonButtonEvent (DECLARE_EVENT, no params).
MyButton->OnClicked().AddUObject(this, &UMyMenuScreen::HandleCloseClicked);
MyButton->OnClicked().RemoveAll(this);
MyButton->SetIsSelected(true);
MyButton->SetIsInteractionEnabled(true);
UCommonInputSubsystem* InputSubsystem = UCommonInputSubsystem::Get(GetOwningLocalPlayer());
const ECommonInputType InputType = InputSubsystem->GetCurrentInputType();  // MouseAndKeyboard, Gamepad, Touch
InputSubsystem->OnInputMethodChangedNative.AddUObject(this, &UMyMenuScreen::HandleInputMethodChanged);

// UCommonUIActionRouterBase is the local-player subsystem that routes input through the activation tree.
if (UCommonUIActionRouterBase* Router = UCommonUIActionRouterBase::Get(*CloseButton))
{
    const ECommonInputMode Mode = Router->GetActiveInputMode();
}

// On a UCommonUserWidget subclass, with UPROPERTY(EditDefaultsOnly) TObjectPtr<UInputAction> BackInputAction:
FUIActionBindingHandle BackHandle = RegisterUIActionBinding(
    FBindUIActionArgs(BackInputAction, /*bShouldDisplayInActionBar=*/true,
        FSimpleDelegate::CreateUObject(this, &UMyMenuScreen::HandleCloseClicked)));

OnInputMethodChangedNative is a DECLARE_EVENT_OneParam, so HandleInputMethodChanged(ECommonInputType) needs no UFUNCTION(). Enhanced Input and Common Input are unified in 5.8: with bEnableEnhancedInputSupport on (UCommonInputSettings::IsEnhancedInputSupportEnabled()), FBindUIActionArgs takes a const UInputAction* and UCommonActivatableWidget::InputMapping / InputMappingPriority push a mapping context on activation.

MVVM

ModelViewViewModel is Beta in 5.8. A view model is a UMVVMViewModelBase; FieldNotify properties get a generated field descriptor, and UE_MVVM_SET_PROPERTY_VALUE compares, assigns and broadcasts in one call.

// MyGameViewModel.h
#pragma once
#include "MVVMViewModelBase.h"
#include "MyGameViewModel.generated.h"

UCLASS()
class MYGAME_API UMyGameViewModel : public UMVVMViewModelBase
{
    GENERATED_BODY()

public:
    void SetScore(int32 NewScore) { UE_MVVM_SET_PROPERTY_VALUE(Score, NewScore); }
    int32 GetScore() const { return Score; }

private:
    UPROPERTY(BlueprintReadOnly, FieldNotify, Getter, meta=(AllowPrivateAccess))
    int32 Score = 0;
};

// Binding at runtime - the UMVVMView extension on the user widget owns the generated bindings.
UMyGameViewModel* ViewModel = NewObject<UMyGameViewModel>(this);
if (UMVVMView* View = UMVVMSubsystem::GetViewFromUserWidget(MyWidget))
{
    View->SetViewModel(TEXT("ScoreViewModel"), ViewModel);   // Name from the Bindings panel
}

UE_MVVM_SET_PROPERTY_VALUE(MemberName, NewValue) expands to SetPropertyValue(MemberName, NewValue, ThisClass::FFieldNotificationClassDescriptor::MemberName). Use UE_MVVM_SET_PROPERTY_VALUE_INLINE for values that cannot be passed as function arguments (bitfields), and UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED(MemberName) when you assigned the member yourself; both end in BroadcastFieldValueChanged(UE::FieldNotification::FFieldId) from INotifyFieldValueChanged.

UHT generates the descriptor for every FieldNotify property and function. Declare fields by hand only under the UCLASS(CustomFieldNotify) class specifier (not a meta key; see Components/Widget.h:215), with the UE_FIELD_NOTIFICATION_DECLARE_CLASS_DESCRIPTOR_BEGIN / UE_FIELD_NOTIFICATION_DECLARE_FIELD(Name, API_STRING) / UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD(Name) / ..._END family in FieldNotificationDeclaration.h (FieldNotification module; the old FieldNotification/ path is deprecated since 5.3), paired with UE_FIELD_NOTIFICATION_IMPLEMENTATION_BEGIN and UE_FIELD_NOTIFICATION_IMPLEMENTATION_END in the .cpp. UMVVMView also exposes GetViewModel(FName), SetViewModelByClass(...) and ExecuteViewModelBindings(FName); UMVVMSubsystem is a UEngineSubsystem and GetViewFromUserWidget is static.

World-Space UI

UWidgetComponent (Components/WidgetComponent.h, UMG module) renders a UUserWidget onto a plane or cylinder in the level.

// In the constructor of AMyCharacter (NameplateComponent is a UPROPERTY member):
NameplateComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("Nameplate"));
NameplateComponent->SetupAttachment(RootComponent);
NameplateComponent->SetWidgetSpace(EWidgetSpace::World);        // or EWidgetSpace::Screen
NameplateComponent->SetDrawSize(FVector2D(256.f, 64.f));
NameplateComponent->SetGeometryMode(EWidgetGeometryMode::Plane);// or Cylinder
NameplateComponent->SetTwoSided(false);
// At runtime:
NameplateComponent->SetWidget(NameplateWidget);
UUserWidget* Current = NameplateComponent->GetUserWidgetObject();
NameplateComponent->SetTickMode(ETickMode::Disabled);   // Then drive updates manually
NameplateComponent->RequestRedraw();

Enable bReceiveHardwareInput only for a widget that must take real mouse input; otherwise drive interaction with a UWidgetInteractionComponent.

Widget Tree and Helper Libraries

WidgetTree->ForEachWidget([](UWidget* Widget) { Widget->SetRenderOpacity(1.f); });
WidgetTree->ForEachWidgetAndDescendants([](UWidget* W) { W->SetIsEnabled(true); });
UButton* Found = WidgetTree->FindWidget<UButton>(TEXT("PlayButton"));
UMyEntryWidget* Built = WidgetTree->ConstructWidget<UMyEntryWidget>(EntryWidgetClass);

UWidgetBlueprintLibrary (Blueprint/WidgetBlueprintLibrary.h) holds the brush, drag-and-drop, FEventReply and FPaintContext drawing helpers; USlateBlueprintLibrary (Blueprint/SlateBlueprintLibrary.h) converts between local, absolute and viewport space. Both are enumerated in references/widget-types.md.

Slate

Use Slate for editor extensions and for runtime widgets UMG does not expose. SWidget is the base; SCompoundWidget is the usual parent for a custom widget.

A custom widget declares its arguments between SLATE_BEGIN_ARGS / SLATE_END_ARGS — SLATE_ATTRIBUTE for a TAttribute<T> that can be bound to a lambda, SLATE_ARGUMENT for a plain value, SLATE_EVENT for a delegate — and builds its children into ChildSlot inside Construct(const FArguments& InArgs). Bind Slate delegates with CreateSP so a destroyed widget never gets called. A complete SCompoundWidget with all three argument kinds: references/slate-patterns.md.

SNew(WidgetType) returns a TSharedRef<WidgetType>; SAssignNew(Var, WidgetType) does the same and stores it in a TSharedPtr. FOnClicked is DECLARE_DELEGATE_RetVal(FReply, FOnClicked), so a click handler must return FReply. UWidget::GetCachedWidget() gives the TSharedPtr<SWidget> behind a UMG widget; UUserWidget::TakeWidget() builds and returns the TSharedRef<SWidget>.

Public TAttribute members on stock Slate widgets are being privatised. Do not read or write them directly; use the accessors named in the deprecation message — Set<Name> to assign, Get<Name>Attribute() to read the TSlateAttributeRef. In 5.8 this hits SCheckBox::PaddingOverride (SetPaddingOverride / GetPaddingOverrideAttribute), SCheckBox::ForegroundColorOverride (SetForegroundColorOverride / GetForegroundColorOverrideAttribute), SEditableText::Font (SetFont / GetFontAttribute), SEditableText::ColorAndOpacity (SetColorAndOpacity / GetColorAndOpacityAttribute) and SMenuAnchor::Placement (SetMenuPlacement / GetPlacementAttribute).

Slate vs UMG: Slate for editor tools and maximum control; UMG for game runtime UI, Blueprint extensibility, animations and BindWidget.

Build.cs

PublicDependencyModuleNames.AddRange(new string[] { "UMG", "Slate", "SlateCore" });
PrivateDependencyModuleNames.AddRange(new string[] {
    "CommonUI", "GameplayTags", // Activatable widgets, buttons, action router, FUIInputConfig; FBindUIActionArgs' FUIActionTag links GameplayTags
    "CommonInput", "EnhancedInput", // UCommonInputSubsystem, ECommonInputType/Mode; UInputAction UPROPERTYs
    "ModelViewViewModel",  // MVVM (Beta in 5.8)
    "FieldNotification" }); // Field-notification declaration macros

Deprecated — do not use

Do not emit Use in 5.8 Source
UUserWidget::RemoveFromViewport() RemoveFromParent() UE_DEPRECATED(5.1) in Blueprint/UserWidget.h:356
UUMGSequencePlayer* returned from PlayAnimation FWidgetAnimationHandle / FWidgetAnimationState UE_DEPRECATED(5.6) in Animation/UMGSequencePlayer.h:29
UUserWidget::ActiveSequencePlayers / StoppedSequencePlayers ActiveAnimations UE_DEPRECATED(5.6) in Blueprint/UserWidget.h:1491,1499
UUserWidget::InitializeInputComponent() bAutomaticallyRegisterInputOnConstruction UE_DEPRECATED(5.7) in Blueprint/UserWidget.h:1713
FWidgetStateBitfield enum-state accessors Binary and named states only UE_DEPRECATED(5.5) in Binding/States/WidgetStateBitfield.h:35
UListView::InitHorizontalEntrySpacing / InitVerticalEntrySpacing SetHorizontalEntrySpacing / SetVerticalEntrySpacing UE_DEPRECATED(5.6) in Components/ListView.h:343,346
USlateBlueprintLibrary::TransformScalarAbsoluteToLocal / TransformVectorAbsoluteToLocal Scalar_LocalToAbsolute / Vector_LocalToAbsolute UE_DEPRECATED(5.6) in Blueprint/SlateBlueprintLibrary.h:77,87
UGameViewportSubsystem::Get(UWorld*) UGameViewportSubsystem::Get() UE_DEPRECATED(5.8) in Blueprint/GameViewportSubsystem.h:64
UButton::WidgetStyle / ColorAndOpacity / ClickMethod direct field access SetStyle / SetColorAndOpacity / SetClickMethod UE_DEPRECATED(5.2) in Components/Button.h:37,42,52
UCommonUIActionRouter UCommonUIActionRouterBase Class name in Input/CommonUIActionRouterBase.h:66
RegisterLinkedPreprocessor(Widget, Processor, int32 DesiredIndex) overload taking FInputPreprocessorRegistrationKey UE_DEPRECATED(5.5) in Input/CommonUIActionRouterBase.h:87
FUIActionBinding::TryCreate(Widget, Args) TryCreate(Widget, Args, UserIndex) UE_DEPRECATED(5.6) in Input/UIActionBinding.h:35
FOnRerouteTouchInputDelegate, UCommonGameViewportClient::OnRerouteTouchInput() FTouchRerouteDelegate, GetRerouteTouchRegistration() / GetRerouteTouchDelegate() UE_DEPRECATED(5.8) in CommonGameViewportClient.h:15,47
#include "Input/CommonInputMode.h" (CommonUI) #include "CommonInputModeTypes.h" (CommonInput) UE_DEPRECATED_HEADER(5.1) in Input/CommonInputMode.h
UMVVMViewModelBase::K2_BroadcastFieldValueChanged the generated property setter UE_DEPRECATED(5.3) in MVVMViewModelBase.h:71

Common Mistakes

Binding in NativeConstruct without unbinding: NativeConstruct runs again every time the widget is re-added, so an unpaired AddDynamic there binds twice. Bind once in NativeOnInitialized (bound widgets are already valid there), or pair NativeConstruct with NativeDestruct — never bind in NativeTick.

Using SetVisibility(Hidden) to close a menu: the widget still occupies layout and stays in the viewport (rooted). Call RemoveFromParent(), or SetVisibility(ESlateVisibility::Collapsed) if it must stay in the tree.

CreateWidget(GetWorld(), ...) for player UI: pass the owning APlayerController so the widget has a local player, split-screen works, and GetOwningPlayer() is valid.

AddDynamic on UCommonButtonBase::OnClicked(): it returns FCommonButtonEvent (a DECLARE_EVENT, not a dynamic delegate). Use AddUObject in NativeOnActivated and RemoveAll(this) in NativeOnDeactivated.

Skipping Super::NativeOnActivated / Super::NativeOnDeactivated: the Super calls broadcast OnActivated() / OnDeactivated(), which the widget's activation-tree node listens to (UIActionRouterTypes.cpp:1372), and push/pop InputMapping, so focus, back handling and input config stop working without them.

No UPROPERTY after RemoveFromParent: the widget is unrooted and collectable. Hold a UPROPERTY() TObjectPtr<> if you intend to re-add it.

Unspecified Z-order: widgets added at the same Z-order have undefined draw order. Pass an explicit value to AddToViewport(ZOrder) and reserve ranges (for example HUD 0-9, menus 10-19, popups 20+). Slate ticks a widget from its paint pass (SWidget.cpp:1511), so NativeTick stops while it is Hidden or Collapsed — do not rely on NativeTick to un-hide it.

Calling SetInputMode under Common UI: it bypasses the activation tree and fights the router. Return an FUIInputConfig from GetDesiredInputConfig() instead.

Related Skills

  • ue-input-system — Enhanced Input, input mapping contexts, FInputModeUIOnly / FInputModeGameAndUI / FInputModeGameOnly, input priority
  • ue-gameplay-framework — where HUD/PlayerController create and own widgets, split-screen ownership
  • ue-cpp-foundations — UPROPERTY/UFUNCTION specifiers, TObjectPtr, GC rules, subsystems
  • ue-editor-tools — Slate in detail customisations, editor utility widgets, UToolMenus
  • ue-materials-rendering — UI materials, UMaterialInstanceDynamic parameters driven from widgets
  • ue-data-assets-tables — data assets and data tables that back list items and icon sets
  • ue-gameplay-abilities — attribute change delegates that drive health/resource bars
  • ue-blueprint-cpp-interop — exposing C++ to Blueprint: UFUNCTION/UPROPERTY meta keys, latent actions and async nodes
  • ue-gameplay-cameras — spring arms, view targets, camera modifiers, shakes and the Gameplay Camera System

Source: SKILL.md on GitHub

No alerts2d5 checks · Risk SAFE
  • Gen Agent Trust Hub2d

    The skill provides comprehensive instructions and reference material for developing user interfaces in Unreal Engine using UMG, Slate, and the Common UI plugin. No security risks or malicious patterns were detected.

  • Socket2d

    No alerts

  • Snyk2d

    Risk: LOW · No issues

  • Runlayer6mo

    3 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at f3742d7. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 3 days ago
metadata
{
  "version": "2.0.0",
  "engine": "5.8"
}

README badge

README badge for quodsoler/unreal-engine-skills/ue-ui-umg-slate