Ue Ui Umg Slate

quodsoler/unreal-engine-skills/skills/ue-ui-umg-slate

作者 quodsolerf3742d7b688690810df369802b90430324e380b9無授權條款收錄於 2026年10月9日更新於 2026年10月9日

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.

AI 產生的概覽

指導以 C++ 撰寫與修正 Unreal Engine 5.8 的 UMG、Slate、Common UI 與 MVVM 介面。

功能
此技能為 Unreal Engine 介面開發提供 C++ 參考指引,涵蓋 UMG 使用者控件、Slate 控件、Common UI 畫面與 MVVM 檢視模型。內容包括控件生命週期覆寫、BindWidget 綁定、控件互動、動畫、輸入模式與焦點、Common UI 啟用堆疊與按鈕、MVVM 欄位通知、世界空間介面,以及控件樹輔助方法。它產出的是程式碼模式與 API 指引而非檔案,並指向隨附的參考文件以取得控件方法表、Common UI 設定與 Slate 模式。
適用情境
在需要以 C++ 撰寫或修正 Unreal Engine 介面時使用,包括 UMG 使用者控件、Slate 控件、Common UI 畫面或 MVVM 檢視模型。當請求提到 UUserWidget、NativeConstruct、BindWidget、CreateWidget、AddToViewport、ESlateVisibility、UListView、SNew、SLATE_BEGIN_ARGS、UCommonActivatableWidget 或 UMVVMViewModelBase 等類別或 API 時同樣適用。輸入模式與 Enhanced Input 會轉交至獨立的輸入技能,編輯器工具中的 Slate 則轉交至獨立的編輯器工具技能。
執行需求
不含指令碼,僅為說明與參考文件。鎖定 Unreal Engine 5.8,並假定存在 Unreal C++ 專案;Common UI 與 MVVM 相關內容假定已啟用對應外掛與模組。若存在 .agents/ue-project-context.md 專案情境檔案,會選擇性讀取。

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, GCWidget Lifecycle
Wiring designer widgets into C++ (meta=(BindWidget))BindWidget
Buttons, text, images, bars, listsWidget Interaction
Playing/stopping UMG animationsWidget Animation
Mouse cursor, focus, SetInputModeInput Mode and Focus
Menus, screen stacks, gamepad, back actionCommon UI
Data binding, view models, field notificationsMVVM
UI rendered in the levelWorld-Space UI
Iterating widgets, drag/drop, brushes, geometryWidget Tree and Helper Libraries
Custom SWidget, SNew, SLATE_BEGIN_ARGSSlate

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

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

cpp
// 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 boolWidget->RemoveFromParent();     // Un-roots - collectable unless a UPROPERTY holds itWidget->SetVisibility(ESlateVisibility::Collapsed);  // Not drawn, takes no spaceWidget->SetVisibility(ESlateVisibility::Hidden);     // Not drawn, still takes spaceWidget->SetVisibility(ESlateVisibility::Visible);    // Drawn, hit-testableWidget->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

cpp
UPROPERTY(meta=(BindWidget))                 // Compile error in the Widget BP if missingTObjectPtr<UTextBlock> ScoreText;UPROPERTY(meta=(BindWidgetOptional))         // May be null - always null-checkTObjectPtr<UTextBlock> SubtitleText;UPROPERTY(Transient, meta=(BindWidgetAnim))  // Transient is required for animation bindingsTObjectPtr<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().

cpp
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.0HealthBar->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 [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].

cpp
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().

cpp
// PlayAnimation(UWidgetAnimation*, StartAtTime=0, NumLoopsToPlay=1,//               EUMGSequencePlayMode::Type=Forward, PlaybackSpeed=1, bRestoreState=false)FWidgetAnimationHandle IntroHandle = PlayAnimation(IntroAnim);IntroHandle.SetUserTag(TEXT("Intro"));PlayAnimationForward(IntroAnim);                        // also PlayAnimationReverseconst 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:

cpp
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 [blocked].

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

cpp
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 oneMenuLayer->RemoveWidget(*Screen);MenuLayer->ClearWidgets();              // GetNumWidgets() reports the current depth

Buttons, input type, action routing

cpp
// 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, TouchInputSubsystem->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.

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

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

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

Widget Tree and Helper Libraries

cpp
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 [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

csharp
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 emitUse in 5.8Source
UUserWidget::RemoveFromViewport()RemoveFromParent()UE_DEPRECATED(5.1) in Blueprint/UserWidget.h:356
UUMGSequencePlayer* returned from PlayAnimationFWidgetAnimationHandle / FWidgetAnimationStateUE_DEPRECATED(5.6) in Animation/UMGSequencePlayer.h:29
UUserWidget::ActiveSequencePlayers / StoppedSequencePlayersActiveAnimationsUE_DEPRECATED(5.6) in Blueprint/UserWidget.h:1491,1499
UUserWidget::InitializeInputComponent()bAutomaticallyRegisterInputOnConstructionUE_DEPRECATED(5.7) in Blueprint/UserWidget.h:1713
FWidgetStateBitfield enum-state accessorsBinary and named states onlyUE_DEPRECATED(5.5) in Binding/States/WidgetStateBitfield.h:35
UListView::InitHorizontalEntrySpacing / InitVerticalEntrySpacingSetHorizontalEntrySpacing / SetVerticalEntrySpacingUE_DEPRECATED(5.6) in Components/ListView.h:343,346
USlateBlueprintLibrary::TransformScalarAbsoluteToLocal / TransformVectorAbsoluteToLocalScalar_LocalToAbsolute / Vector_LocalToAbsoluteUE_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 accessSetStyle / SetColorAndOpacity / SetClickMethodUE_DEPRECATED(5.2) in Components/Button.h:37,42,52
UCommonUIActionRouterUCommonUIActionRouterBaseClass name in Input/CommonUIActionRouterBase.h:66
RegisterLinkedPreprocessor(Widget, Processor, int32 DesiredIndex)overload taking FInputPreprocessorRegistrationKeyUE_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_BroadcastFieldValueChangedthe generated property setterUE_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

來源與署名

來源:quodsoler/unreal-engine-skills位於skills/ue-ui-umg-slate提交f3742d7

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架