UE5でカスタムWindowを作成する時の書き方
Unreal Engine 5のPluginでカスタムウィンドウを作成するときのメモ
基本フロー概要
- Editorモジュールを用意:
「編集」→「プラグイン」→「追加」から、エディタ スタンドアロン ウィンドウ
のテンプレートを使うとスムーズです。
手動で設定する場合は、*.Build.csファイルでSlate
やSlateCore
への依存を記述します。 - SCompoundWidget継承クラス作成:
SMyWindowWidget : public SCompoundWidget のようなクラスを用意し、そのConstruct()メソッドでUIを定義することで、新規ウィジェットを実装できます。 - Window生成:
FGlobalTabmanager::Get()->RegisterNomadTabSpawner() や FLevelEditorModule経由で独自タブを登録し、そのタブ内に SNew(SMyWindowWidget) を配置することでカスタムウィンドウをエディタ内に表示します。
ウィジェット生成の基本
SNew(WidgetClass)
SNewマクロは新規ウィジェットインスタンス生成の基本です。
SVerticalBox, SHorizontalBox, STextBlock など、用意されたWidgetをチェーンで組み立てられます。
例:
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight() // 子要素の高さに合わせる
[
SNew(STextBlock)
.Text(FText::FromString("Hello World"))
]
+ SVerticalBox::Slot()
.FillHeight(1.0f) // 余ったスペースをすべて使用
[
SNew(SEditableTextBox)
.Text(FText::FromString("Default Text"))
]
];
SAssignNew(MyWidgetRef, WidgetClass)
SAssignNewで生成と同時にTSharedPtrに格納し、後から値の更新やイベントハンドリングが可能になります。
TSharedPtr<SEditableTextBox> MyTextBox;
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SAssignNew(MyTextBox, SEditableTextBox)
.Text(FText::FromString("Editable"))
]
];
// 後で MyTextBox->SetText(...) で動的に変更可能
よく使うWidgetとプロパティ
テキスト表示関連
- STextBlock:
.Text(FText::FromString("文字列")) でテキスト指定
.Justification(ETextJustify::Center) でテキストの揃え方向指定
入力系ウィジェット
- SEditableTextBox:入力可能なテキストフィールド
.OnTextCommitted(this, &ThisClass::OnTextCommitted) で確定時イベント
.OnTextChanged(this, &ThisClass::OnTextChanged) で変更検知 - SSlider:スライダー
.MinValue(0.0f), .MaxValue(100.0f) など範囲指定
.Value(this, &ThisClass::GetSliderValue)で値取得、
.OnValueChanged(this, &ThisClass::SetSliderValue)で値変更を反映(双方向データバインド) - SCheckBox:チェックボックス
.IsChecked(this, &ThisClass::GetCheckedState),
.OnCheckStateChanged(this, &ThisClass::OnCheckStateChanged)で状態の同期
レイアウト用
-
SVerticalBox / SHorizontalBox:
縦・横方向へのWidget配置。
+ SVerticalBox::Slot()
.AutoHeight()
.Padding(5)
などでサイズ・余白指定。 -
SScrollBox:
中身が大きい場合にスクロール可能な領域。親でのサイズ強制が必須
.Orientation(Orient_Vertical)などで方向指定。 -
SWidgetSwitcher(複数ウィジェットの切り替え):
SWidgetSwitcherは複数のウィジェットをスロットとして持ち、その中から1つをアクティブにして表示します。
タブや段階的な画面遷移を簡易的に実装する際に便利です。
SAssignNew(WidgetSwitcher, SWidgetSwitcher)
+ SWidgetSwitcher::Slot()
[
// スロット1番目
SNew(STextBlock).Text(FText::FromString("First View"))
]
+ SWidgetSwitcher::Slot()
[
// スロット2番目
SNew(STextBlock).Text(FText::FromString("Second View"))
];
WidgetSwitcher->SetActiveWidgetIndex(1); のように呼ぶことで、別のスロットへ切り替えが可能です。
サイズ指定のバリエーション
WidgetのSlotに対して以下のメソッドでサイズを制御可能です。
- AutoSize() / AutoHeight() / AutoWidth():
コンテンツに合わせて自動サイズ調整。
例:.AutoHeight()は表示内容に基づいて高さを自動決定。 - FillHeight(float) / FillWidth(float):
余ったスペースを指定割合で埋める。
複数のフィル指定がある場合、数値が比率となる。 - FixedSize(float):
固定ピクセルサイズで表示。
コンテンツ量に関わらず同じ大きさをキープ。 - MaxHeight(float) / MaxWidth(float):
ウィジェットの最大サイズを制限。
AutoHeight()でコンテンツが増えてもこれ以上は拡張しない。
プロパティ指定方法の違い (.Textや.OnClickなど)
- 直接指定:
.Text(FText::FromString("固定テキスト")) のように値を直接指定。 - メンバ関数バインド:
.Text(this, &ThisClass::GetDynamicText) のようにメンバ関数をバインドすると、更新のたびに関数が呼ばれ動的なテキストを返せます。 - ラムダ指定 (.Text_Lambda など):
.Text_Lambda([](){ return FText::FromString("動的テキスト"); })
.OnClicked_Lambda([](){ return FReply::Handled(); })
のように即時定義の無名関数を使って動的な値やイベントハンドリングが可能です。
ラムダ指定は簡潔ですが、キャプチャに注意が必要です(ウィジェット破棄時やオーナーが無効になった場合への対処など)。
データバインディング
ゲッター・セッター関数を用意して.Value(this, &ThisClass::GetXxxx), .OnValueChanged(this, &ThisClass::SetXxxx)で紐づけると、UI変更時に自動的にデータ同期可能です。
float MyValue = 1.0f;
float GetSliderValue() const { return MyValue; }
void SetSliderValue(float NewValue) { MyValue = NewValue; }
ChildSlot
[
SNew(SSlider)
.MinValue(0.0f)
.MaxValue(10.0f)
.Value(this, &ThisClass::GetSliderValue)
.OnValueChanged(this, &ThisClass::SetSliderValue)
];
レイアウト調整Tips
- .Padding(X):余白
- .AutoHeight():内容に合わせた高さ
- .FillHeight(1.0f):残りスペースをすべて占有
- 水平方向は .FillWidth(), .AutoWidth() も同様
カラーやスタイル変更
- STextBlockやSEditableTextBoxは
.ColorAndOpacity(FLinearColor::White)で文字色、
.Font(FSlateFontInfo())でフォント指定可能。
まとめ
- SNewでウィジェット作成
- SAssignNewで参照保持
- AutoHeight, FillHeight, FixedSize, MaxHeightで自由自在にサイズ調整
- .Textや.OnClickは固定値指定、メンバ関数指定、ラムダ指定が可能
- SVerticalBox, SHorizontalBox、SScrollBoxなどでレイアウト
- STextBlock, SEditableTextBox, SSlider, SCheckBoxで基本的なUIを構築
- プロパティバインディングで常に最新状態をUIと同期
他にもSBorder
などの便利なWidgetがUE側で用意されています。
Discussion