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.
Per-widget method tables (setters, delegates, enums) live in references/widget-types.md [blocked]. Full Common UI plugin setup lives in references/common-ui-setup.md [blocked]. A complete custom Slate widget lives in references/slate-patterns.md [blocked].
Widget Lifecycle
Input handlers return FReply::Handled() to consume the event or FReply::Unhandled() to let it bubble.
Creation, viewport, visibility
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
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().
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 [blocked].
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 [blocked].
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().
Input Mode and Focus
ue-input-system owns input modes and Enhanced Input. Minimal correct form:
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 [blocked].
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.
Buttons, input type, action routing
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.
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.
Enable bReceiveHardwareInput only for a widget that must take real mouse input; otherwise drive interaction with a UWidgetInteractionComponent.
Widget Tree and Helper Libraries
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 [blocked].
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 [blocked].
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
Deprecated — do not use
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 priorityue-gameplay-framework— where HUD/PlayerController create and own widgets, split-screen ownershipue-cpp-foundations—UPROPERTY/UFUNCTIONspecifiers,TObjectPtr, GC rules, subsystemsue-editor-tools— Slate in detail customisations, editor utility widgets,UToolMenusue-materials-rendering— UI materials,UMaterialInstanceDynamicparameters driven from widgetsue-data-assets-tables— data assets and data tables that back list items and icon setsue-gameplay-abilities— attribute change delegates that drive health/resource barsue-blueprint-cpp-interop— exposing C++ to Blueprint: UFUNCTION/UPROPERTY meta keys, latent actions and async nodesue-gameplay-cameras— spring arms, view targets, camera modifiers, shakes and the Gameplay Camera System


