ue-ui-umg-slate について
UMG、Slate、Common UI を使う Unreal Engine 5.8 の UI 開発向けスキルガイドです。ウィジェットのライフサイクル、操作、アニメーション、入力フォーカス、リスト、MVVM を扱います。
主な機能
- 01ウィジェットのライフサイクルと作成
- 02UMG の操作とリスト
- 03ウィジェットアニメーションと入力フォーカス
- 04Common UI のアクティベーションスタックと入力ルーティング
- 05Slate と MVVM のガイド
活用シーン
- 01ランタイムウィジェットの作成と管理
- 02ボタンのバインドとテキストや進捗の表示
- 03メニュー画面とアクティベーションスタックの構築
- 04データバインディングやカスタム Slate ウィジェットの実装
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ quodsoler/ unreal-engine-skills --skill ue-ui-umg-slateインストール後、Claude Code で/ue-ui-umg-slateを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/common-ui-setup.mdslate-patterns.mdwidget-types.md詳細
UE UI:UMG、Slate、Common UI
対象エンジン:UE 5.8。以下の API は 5.8 のヘッダーに照らして確認済みです。古い形式は「非推奨 — 使用しないでください」に記載しています。
UMG は Slate(Slate、SlateCore)上に構築されたランタイム UI フレームワーク(UMG モジュール、Engine/Source/Runtime/UMG/Public)です。Common UI(プラグイン、5.8 で本番利用可能)は、クロスプラットフォームの入力ルーティング、アクティベーションスタック、プラットフォーム対応ボタンを追加します。Model View Viewmodel(プラグイン、5.8 でベータ)は、FieldNotification 上に宣言的なデータバインディングを追加します。
コンテキスト
.agents/ue-project-context.md が存在する場合は読み込んでください(モジュール名、規約、有効なプラグイン、GAS/ネットワーク設定)。ファイルがない場合も作業を中断しないでください。
依頼内容とコードベースから該当領域を特定してください。妥当な解釈が 2 通りあり、それぞれで異なるコードになる場合に限り、確認してください。
| 依頼の内容… | 参照先 |
|---|---|
| ウィジェットクラス、オーバーライド、作成、可視性、GC | ウィジェットのライフサイクル |
デザイナーのウィジェットを C++ に接続する(meta=(BindWidget)) | BindWidget |
| ボタン、テキスト、画像、バー、リスト | ウィジェットの操作 |
| UMG アニメーションの再生/停止 | ウィジェットアニメーション |
マウスカーソル、フォーカス、SetInputMode | 入力モードとフォーカス |
| メニュー、画面スタック、ゲームパッド、戻る操作 | Common UI |
| データバインディング、ビューモデル、フィールド通知 | MVVM |
| レベル内に描画される UI | ワールド空間 UI |
| ウィジェットの反復処理、ドラッグ&ドロップ、ブラシ、ジオメトリ | ウィジェットツリーとヘルパーライブラリ |
カスタム SWidget、SNew、SLATE_BEGIN_ARGS | Slate |
ウィジェットごとのメソッド一覧(セッター、デリゲート、列挙型)は references/widget-types.md にあります。Common UI プラグインのセットアップ全体は references/common-ui-setup.md にあります。カスタム Slate ウィジェットの完全な例は references/slate-patterns.md にあります。
ウィジェットのライフサイクル
// 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();
}
オーバーライド(Blueprint/UserWidget.h の記述どおり) | 実行タイミング |
|---|---|
virtual void NativeOnInitialized() override; | インスタンスごとに 1 回、ウィジェットオブジェクトの構築後 |
virtual void NativePreConstruct() override; | Slate ツリーの再構築後、NativeConstruct の直前(UserWidget.cpp:1231)。デザイナーでも実行されます |
virtual void NativeConstruct() override; | Slate ウィジェットが親に追加されたとき — ここでデリゲートをバインドします |
virtual void NativeDestruct() override; | Slate ウィジェットが削除されたとき — ここでバインドを解除します |
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; | ティック中、毎フレーム |
virtual int32 NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override; | カスタム描画。最後に使用したレイヤー ID を返します |
virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override; | ポインターが押されたとき |
virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override; | フォーカス中にキーが押されたとき |
virtual FReply NativeOnFocusReceived(const FGeometry& InGeometry, const FFocusEvent& InFocusEvent) override; | このウィジェットがフォーカスを得たとき |
virtual void NativeOnAddedToFocusPath(const FFocusEvent& InFocusEvent) override; | このウィジェットまたは子孫がフォーカスを得たとき |
virtual bool Initialize() override; | ウィジェットツリーを構築します。Super::Initialize() を呼び、その結果を返します |
virtual TSharedRef<SWidget> RebuildWidget() override; | 基盤となる Slate ウィジェットを構築します |
virtual void ReleaseSlateResources(bool bReleaseChildren) override; | キャッシュ済みの TSharedPtr<SWidget> メンバーをここで解放します |
入力ハンドラーは、イベントを処理する場合は FReply::Handled() を返し、イベントを上位に伝播させる場合は FReply::Unhandled() を返します。
作成、ビューポート、表示状態
// 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は描画しますが、ウィジェットとその子ウィジェットへの入力を通過させます。SelfHitTestInvisibleはウィジェット自体への入力のみを通過させます。ウィジェットをRemoveFromParent後も存続させる必要がある場合は、UPROPERTY() TObjectPtr<UMyWidget>を保持します。GetOwningPlayer()は所有元のAPlayerControllerを返し、GetOwningPlayer<AMyPlayerController>()はキャストも行います。
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;
ルール:C++メンバー名はWidget Blueprintのウィジェット名と完全に一致する必要があります(大文字と小文字を区別)。宣言する型は、デザイナーウィジェットのクラスと一致するか、その基底クラスである必要があります。バインドされたメンバーはInitialize()内でNativeOnInitializedの実行前に割り当てられるため(UserWidget.cpp:153,175)、NativeOnInitialized、NativePreConstruct、NativeConstructで有効です。インスタンスごとに一度だけバインドするデリゲートはNativeOnInitializedでバインドします。Categoryを指定せず、protectedとして宣言します。
ウィジェット操作
UMGコンポーネントの動的マルチキャストデリゲートにはAddDynamicを使用するため、ハンドラーは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));
UButton、UTextBlock、UImage、UProgressBar、UScrollBox、UWidgetSwitcher、UCheckBox、UEditableTextBox、USlider、UComboBoxStringおよびUWidget基底クラスのメソッドと列挙型の一覧は、references/widget-types.mdにあります。
リスト:UListView、UTileView、UTreeView
これら3つはすべて仮想化されており、表示中のエントリーウィジェットのみが存在し、再利用されます。アイテムはUObject*です。エントリーウィジェットはUUserWidgetを継承し、IUserObjectListEntryを実装して、virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override;をオーバーライドします(最初にIUserObjectListEntry::NativeOnListItemObjectSetを呼び出してください)。エントリーウィジェットの完全な例とUListViewメソッド一覧は、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はBlueprint専用のプライベートデリゲートです。C++からは、ネイティブイベントItemList->OnItemClicked().AddUObject(...)(FSimpleListItemEvent、Components/ListViewBase.h:48。OnItemSelectionChanged()も参照)をバインドするか、UListViewのサブクラスでvirtual void OnItemClickedInternal(UObject* Item) override;をオーバーライドします。エントリーウィジェット内では、GetListItem<UMyItemData>()でアイテムを取得し、インターフェイスメンバーのIsListItemSelected()で選択状態を確認します(Blueprint/IUserListEntry.h:32)。
ウィジェットアニメーション
PlayAnimationとその派生関数はFWidgetAnimationHandleを返します(Animation/WidgetAnimationHandle.h)。シーケンスプレーヤーへのポインターではなく、このハンドルを保持してください。有効なハンドルでも、アニメーション終了後は状態を取得できない場合があるため、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);
入力モードとフォーカス
入力モードとEnhanced Inputはue-input-systemが管理します。正しい最小限の形式は次のとおりです。
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には、SetWidgetToFocusとSetLockMouseToViewportBehaviorもあります。入力モードはNativeConstructではなく、ウィジェットを追加したコード(HUD、PlayerController、GameMode)から設定してください。Common UIが有効な場合は、SetInputModeを呼び出さず、代わりにFUIInputConfigを返してください。
Common UI
CommonUI プラグイン(CommonUI と CommonInput の両モジュールを含みます)を有効にし、両方のモジュールを Build.cs に追加して、ビューポートクライアントクラスを UCommonGameViewportClient に設定します。これはゲームに入力が渡る前に、UI アクションルーターへ入力を振り分けます(CommonGameViewportClient.h:21)。ゲームパッド/マウス/タッチの変更は、UCommonInputSubsystem の FCommonInputPreprocessor によって検出され、そのサブシステムからブロードキャストされます。セットアップの詳細、レイヤーアーキテクチャ、設定キーについては、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(); }
パブリック API:ActivateWidget()、DeactivateWidget()、IsActivated()、GetDesiredFocusTarget()、ClearFocusRestorationTarget()、RequestRefreshFocus()、および動的ではない OnActivated()/OnDeactivated() デリゲート。BP_GetDesiredFocusTarget は NativeGetDesiredFocusTarget が呼び出す BlueprintImplementableEvent です。C++ ではネイティブ版をオーバーライドしてください。編集可能なデフォルト値:bAutoActivate、bIsBackHandler、bIsBackActionDisplayedInActionBar、bIsModal、bAutoRestoreFocus、bSetVisibilityOnActivated/ActivatedVisibility、bSetVisibilityOnDeactivated/DeactivatedVisibility。ECommonInputMode は Menu(UI のみ)、Game(ゲームのみ)、または All です。
コンテナー
UCommonActivatableWidgetContainerBase(Widgets/CommonActivatableWidgetContainer.h)は基底クラスです。UCommonActivatableWidgetStack は最上位のウィジェットを表示し、それが非アクティブになると、その下にあるウィジェットを再アクティブ化します。UCommonActivatableWidgetQueue は一度に 1 つを表示し、アクティブなウィジェットが非アクティブになると次に進みます。UCommonActivatableWidgetSwitcher はインデックスベースのスイッチャーであり、スタックではありません。ここでは使用しないでください。
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
ボタン、入力タイプ、アクションルーティング
// 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 は DECLARE_EVENT_OneParam なので、HandleInputMethodChanged(ECommonInputType) に UFUNCTION() は必要ありません。5.8 では Enhanced Input と Common Input が統合されています。bEnableEnhancedInputSupport を有効にすると(UCommonInputSettings::IsEnhancedInputSupportEnabled())、FBindUIActionArgs は const UInputAction* を受け取り、UCommonActivatableWidget::InputMapping/InputMappingPriority はアクティブ化時にマッピングコンテキストを適用します。
MVVM
ModelViewViewModel は 5.8 ではベータ版です。ビューモデルは UMVVMViewModelBase です。FieldNotify プロパティにはフィールド記述子が生成され、UE_MVVM_SET_PROPERTY_VALUE は 1 回の呼び出しで比較、代入、ブロードキャストを行います。
// 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) は SetPropertyValue(MemberName, NewValue, ThisClass::FFieldNotificationClassDescriptor::MemberName) に展開されます。関数の引数として渡せない値(ビットフィールド)には UE_MVVM_SET_PROPERTY_VALUE_INLINE を使用し、自分でメンバーに代入した場合は UE_MVVM_BROADCAST_FIELD_VALUE_CHANGED(MemberName) を使用してください。どちらも、最終的には INotifyFieldValueChanged の BroadcastFieldValueChanged(UE::FieldNotification::FFieldId) を呼び出します。
UHT はすべての FieldNotify プロパティと関数について記述子を生成します。フィールドを手動で宣言するのは、UCLASS(CustomFieldNotify) クラス指定子(メタキーではありません。Components/Widget.h:215 を参照)を使用する場合に限ります。その際は、FieldNotificationDeclaration.h(FieldNotification モジュール。旧 FieldNotification/ パスは 5.3 以降非推奨)にある UE_FIELD_NOTIFICATION_DECLARE_CLASS_DESCRIPTOR_BEGIN/UE_FIELD_NOTIFICATION_DECLARE_FIELD(Name, API_STRING)/UE_FIELD_NOTIFICATION_DECLARE_ENUM_FIELD(Name)/..._END の各マクロと、.cpp での UE_FIELD_NOTIFICATION_IMPLEMENTATION_BEGIN および UE_FIELD_NOTIFICATION_IMPLEMENTATION_END を組み合わせてください。UMVVMView は GetViewModel(FName)、SetViewModelByClass(...)、ExecuteViewModelBindings(FName) も公開します。UMVVMSubsystem は UEngineSubsystem で、GetViewFromUserWidget は静的です。
ワールド空間 UI
UWidgetComponent(Components/WidgetComponent.h、UMG モジュール)は、レベル内の平面または円柱に UUserWidget を描画します。
// 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();
実際のマウス入力を受け取る必要があるウィジェットに限り、bReceiveHardwareInput を有効にしてください。それ以外の場合は、UWidgetInteractionComponent を使って操作してください。
ウィジェットツリーとヘルパーライブラリ
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)には、ブラシ、ドラッグ&ドロップ、FEventReply、FPaintContext の描画ヘルパーが用意されています。USlateBlueprintLibrary(Blueprint/SlateBlueprintLibrary.h)は、ローカル空間、絶対空間、ビューポート空間の間で変換します。どちらもreferences/widget-types.mdに記載されています。
Slate
エディター拡張や、UMG では公開されていないランタイムウィジェットには Slate を使用します。SWidget が基底クラスで、カスタムウィジェットの親クラスには通常 SCompoundWidget を使用します。
カスタムウィジェットでは、SLATE_BEGIN_ARGS / SLATE_END_ARGS の間に引数を宣言します。ラムダにバインドできる TAttribute<T> には SLATE_ATTRIBUTE、通常の値には SLATE_ARGUMENT、デリゲートには SLATE_EVENT を使用します。Construct(const FArguments& InArgs) 内で、子ウィジェットを ChildSlot に組み立てます。Slate デリゲートのバインドには CreateSP を使用し、破棄されたウィジェットが呼び出されないようにします。3 種類すべての引数を使用した SCompoundWidget の完全な例は、references/slate-patterns.mdを参照してください。
SNew(WidgetType) は TSharedRef<WidgetType> を返します。SAssignNew(Var, WidgetType) も同様ですが、TSharedPtr に格納します。FOnClicked は DECLARE_DELEGATE_RetVal(FReply, FOnClicked) なので、クリックハンドラーは FReply を返す必要があります。UWidget::GetCachedWidget() は、UMG ウィジェットの背後にある TSharedPtr<SWidget> を取得します。UUserWidget::TakeWidget() は TSharedRef<SWidget> を構築して返します。
標準 Slate ウィジェットの公開 TAttribute メンバーは、プライベート化が進められています。 直接読み書きしないでください。非推奨メッセージに記載されたアクセサーを使用します。値を設定するには Set<Name>、TSlateAttributeRef を読み取るには Get<Name>Attribute() を使用してください。5.8 では、SCheckBox::PaddingOverride(SetPaddingOverride / GetPaddingOverrideAttribute)、SCheckBox::ForegroundColorOverride(SetForegroundColorOverride / GetForegroundColorOverrideAttribute)、SEditableText::Font(SetFont / GetFontAttribute)、SEditableText::ColorAndOpacity(SetColorAndOpacity / GetColorAndOpacityAttribute)、SMenuAnchor::Placement(SetMenuPlacement / GetPlacementAttribute)が対象です。
Slate と UMG: エディターツールや最大限の制御には Slate を、ゲームのランタイム UI、Blueprint による拡張性、アニメーション、BindWidget には UMG を使用します。
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
非推奨 — 使用しないでください
| 使用しないでください | 5.8 で使用 | ソース |
|---|---|---|
UUserWidget::RemoveFromViewport() | RemoveFromParent() | Blueprint/UserWidget.h:356 の UE_DEPRECATED(5.1) |
PlayAnimation から返される UUMGSequencePlayer* | FWidgetAnimationHandle / FWidgetAnimationState | Animation/UMGSequencePlayer.h:29 の UE_DEPRECATED(5.6) |
UUserWidget::ActiveSequencePlayers / StoppedSequencePlayers | ActiveAnimations | Blueprint/UserWidget.h:1491,1499 の UE_DEPRECATED(5.6) |
UUserWidget::InitializeInputComponent() | bAutomaticallyRegisterInputOnConstruction | Blueprint/UserWidget.h:1713 の UE_DEPRECATED(5.7) |
FWidgetStateBitfield の列挙型状態アクセサー | バイナリ状態および名前付き状態のみ | Binding/States/WidgetStateBitfield.h:35 の UE_DEPRECATED(5.5) |
UListView::InitHorizontalEntrySpacing / InitVerticalEntrySpacing | SetHorizontalEntrySpacing / SetVerticalEntrySpacing | Components/ListView.h:343,346 の UE_DEPRECATED(5.6) |
USlateBlueprintLibrary::TransformScalarAbsoluteToLocal / TransformVectorAbsoluteToLocal | Scalar_LocalToAbsolute / Vector_LocalToAbsolute | Blueprint/SlateBlueprintLibrary.h:77,87 の UE_DEPRECATED(5.6) |
UGameViewportSubsystem::Get(UWorld*) | UGameViewportSubsystem::Get() | Blueprint/GameViewportSubsystem.h:64 の UE_DEPRECATED(5.8) |
UButton::WidgetStyle / ColorAndOpacity / ClickMethod への直接的なフィールドアクセス | SetStyle / SetColorAndOpacity / SetClickMethod | Components/Button.h:37,42,52 の UE_DEPRECATED(5.2) |
UCommonUIActionRouter | UCommonUIActionRouterBase | Input/CommonUIActionRouterBase.h:66 のクラス名 |
RegisterLinkedPreprocessor(Widget, Processor, int32 DesiredIndex) | FInputPreprocessorRegistrationKey を受け取るオーバーロード | Input/CommonUIActionRouterBase.h:87 の UE_DEPRECATED(5.5) |
FUIActionBinding::TryCreate(Widget, Args) | TryCreate(Widget, Args, UserIndex) | Input/UIActionBinding.h:35 の UE_DEPRECATED(5.6) |
FOnRerouteTouchInputDelegate、UCommonGameViewportClient::OnRerouteTouchInput() | FTouchRerouteDelegate、GetRerouteTouchRegistration() / GetRerouteTouchDelegate() | CommonGameViewportClient.h:15,47 の UE_DEPRECATED(5.8) |
#include "Input/CommonInputMode.h"(CommonUI) | #include "CommonInputModeTypes.h"(CommonInput) | Input/CommonInputMode.h の UE_DEPRECATED_HEADER(5.1) |
UMVVMViewModelBase::K2_BroadcastFieldValueChanged | 生成されたプロパティセッター | MVVMViewModelBase.h:71 の UE_DEPRECATED(5.3) |
よくある間違い
バインド解除せずにNativeConstructでバインドする: ウィジェットが追加されるたびにNativeConstructが再実行されるため、対応するバインド解除のないAddDynamicをそこに置くと、二重にバインドされます。NativeOnInitializedで一度だけバインドする(その時点でバインド対象のウィジェットはすでに有効です)か、NativeConstructとNativeDestructを対にして使ってください。NativeTickでは決してバインドしないでください。
メニューを閉じるためにSetVisibility(Hidden)を使う: ウィジェットはレイアウト上の領域を占めたままで、ビューポートにも(ルート化された状態で)残ります。RemoveFromParent()を呼び出すか、ツリー内に残す必要がある場合はSetVisibility(ESlateVisibility::Collapsed)を使ってください。
プレイヤー UI にCreateWidget(GetWorld(), ...)を使う: 所有するAPlayerControllerを渡してください。そうすればウィジェットにローカルプレイヤーが設定され、画面分割が機能し、GetOwningPlayer()も有効になります。
UCommonButtonBase::OnClicked()でAddDynamicを使う: これはFCommonButtonEventを返します(動的デリゲートではなく、DECLARE_EVENTです)。NativeOnActivatedでAddUObjectを使い、NativeOnDeactivatedでRemoveAll(this)を呼び出してください。
Super::NativeOnActivated/Super::NativeOnDeactivatedを省略する: Super の呼び出しはOnActivated()/OnDeactivated()をブロードキャストします。これらはウィジェットのアクティベーションツリーノード(UIActionRouterTypes.cpp:1372)がリッスンし、InputMappingをプッシュ/ポップするため、呼び出さないとフォーカス、戻る操作の処理、入力設定が機能しなくなります。
RemoveFromParent後にUPROPERTYを使わない: ウィジェットはルート解除され、ガベージコレクションの対象になります。再追加する予定がある場合は、UPROPERTY() TObjectPtr<>で保持してください。
Z オーダーを指定しない: 同じ Z オーダーで追加されたウィジェットの描画順序は未定義です。AddToViewport(ZOrder)に明示的な値を渡し、範囲を割り当ててください(例:HUD は 0~9、メニューは 10~19、ポップアップは 20 以上)。Slate はペイントパス中にウィジェットをティックするため(SWidget.cpp:1511)、HiddenまたはCollapsedの間はNativeTickが停止します。ウィジェットを表示状態に戻すためにNativeTickを頼りにしないでください。
Common UI の下でSetInputModeを呼び出す: アクティベーションツリーを迂回し、ルーターと競合します。代わりに、GetDesiredInputConfig()からFUIInputConfigを返してください。
関連スキル
ue-input-system— Enhanced Input、入力マッピングコンテキスト、FInputModeUIOnly/FInputModeGameAndUI/FInputModeGameOnly、入力優先度ue-gameplay-framework— HUD/PlayerController がウィジェットを作成して所有する場所、画面分割時の所有権ue-cpp-foundations—UPROPERTY/UFUNCTION指定子、TObjectPtr、GC ルール、サブシステムue-editor-tools— Slate の詳細なカスタマイズ、エディタユーティリティウィジェット、UToolMenusue-materials-rendering— UI マテリアル、ウィジェットから駆動されるUMaterialInstanceDynamicのパラメーターue-data-assets-tables— リスト項目やアイコンセットを支えるデータアセットとデータテーブルue-gameplay-abilities— ヘルス/リソースバーを駆動する属性変更デリゲートue-blueprint-cpp-interop— C++ を Blueprint に公開する方法:UFUNCTION/UPROPERTY のメタキー、潜在アクション、非同期ノードue-gameplay-cameras— スプリングアーム、ビュ-ターゲット、カメラモディファイア、シェイク、Gameplay Camera System