この記事の要点
- UMG ウィジェットをマウスでドラッグ移動させるには
OnMouseButtonDown+OnMouseMove+OnMouseButtonUpの組み合わせ - 正式なドラッグ&ドロップは
DetectDragIfPressed+ DragDropOperation - 位置の反映は
SetRenderTranslationまたは親 Canvas のPositionプロパティ - マウス位置取得は
GetMousePositionOnViewportまたは PlayerController のGetMousePosition - 入力モードを UI Only または Game and UI にしないとマウスイベントが UMG に届かない
12 種類のマウス操作 UI
Unreal Engine の UMG で「マウスで動かす UI」を作る方法は大きく 2 つあります:
| シンプル移動 | 正式ドラッグ&ドロップ | |
|---|---|---|
| 用途 | ウィジェット自身が動く | UI 間でアイテム移動 |
| 主な API | OnMouseButtonDown/Move/Up | DetectDragIfPressed + DragDropOperation |
| ペイロード | なし | Operation オブジェクトで運ぶ |
| 視覚フィードバック | 自前 | Drag Visual ウィジェットで自動 |
| 難易度 | 中 | やや高 |
2シンプル移動: ウィジェットをドラッグ
Windowsアプリのウィンドウのように、ウィジェット自身をマウスで掴んで動かす実装です。
Blueprint 実装
[User Widget (例: WBP_DraggableWindow)]
変数:
bIsDragging (Boolean)
DragOffset (Vector2D)
[OnMouseButtonDown] override
Input: MyGeometry, MouseEvent
- IsLeftMouseButtonDown? → true
- bIsDragging = true
- DragOffset = MouseEvent.GetScreenSpacePosition - MyGeometry.GetAbsolutePosition
- Return Handled() / Capture Mouse
[OnMouseMove] override
- if bIsDragging
- NewPos = MouseEvent.GetScreenSpacePosition - DragOffset
- SetPositionInViewport(NewPos) ← Self
- Return Handled
[OnMouseButtonUp] override
- bIsDragging = false
- Return Handled / Release Mouse Capture
C++ 実装
// UDraggableWindow.h
UCLASS()
class MYGAME_API UDraggableWindow : public UUserWidget
{
GENERATED_BODY()
protected:
virtual FReply NativeOnMouseButtonDown(
const FGeometry& InGeometry,
const FPointerEvent& InMouseEvent) override;
virtual FReply NativeOnMouseMove(
const FGeometry& InGeometry,
const FPointerEvent& InMouseEvent) override;
virtual FReply NativeOnMouseButtonUp(
const FGeometry& InGeometry,
const FPointerEvent& InMouseEvent) override;
bool bIsDragging = false;
FVector2D DragOffset;
};
// UDraggableWindow.cpp
FReply UDraggableWindow::NativeOnMouseButtonDown(
const FGeometry& Geo, const FPointerEvent& Ev)
{
if (Ev.GetEffectingButton() == EKeys::LeftMouseButton)
{
bIsDragging = true;
DragOffset = Ev.GetScreenSpacePosition() -
Geo.GetAbsolutePosition();
return FReply::Handled().CaptureMouse(TakeWidget());
}
return FReply::Unhandled();
}
FReply UDraggableWindow::NativeOnMouseMove(
const FGeometry& Geo, const FPointerEvent& Ev)
{
if (bIsDragging)
{
FVector2D NewPos = Ev.GetScreenSpacePosition() - DragOffset;
SetPositionInViewport(NewPos, /*bRemoveDPIScale=*/false);
return FReply::Handled();
}
return FReply::Unhandled();
}
FReply UDraggableWindow::NativeOnMouseButtonUp(
const FGeometry& Geo, const FPointerEvent& Ev)
{
bIsDragging = false;
return FReply::Handled().ReleaseMouseCapture();
}
3正式なドラッグ&ドロップ(インベントリ等)
アイテムスロット間でアイコンをドラッグして移動する場合は、Unreal 標準の Drag-and-Drop システムを使います:
手順1: DragDropOperation 派生クラスを作る
[Blueprint Class > DragDropOperation 派生]
名前: BPDDO_Item
変数を追加:
PayloadItemID (Name)
PayloadIcon (Texture2D)
SourceSlot (UserWidget Reference)
手順2: ドラッグ元のウィジェットで Detect
[InventorySlot WBP]
[OnMouseButtonDown]
Input: MouseEvent
→ Detect Drag if Pressed (Pointer Event, Key=Left Mouse Button)
→ Return Handled
[OnDragDetected]
Input: MouseEvent
- Create Widget (W_DragVisual) ← 半透明のアイコン
- Create DragDropOperation (Class = BPDDO_Item)
- PayloadItemID = この slot の ItemID
- PayloadIcon = この slot の Texture
- SourceSlot = Self
- Default Drag Visual = W_DragVisual
- Pivot = Center Center
- Return Operation
手順3: ドロップ先で受け取る
[InventorySlot WBP / 他の Slot]
[OnDrop]
Input: Operation
- Cast to BPDDO_Item
- if Success:
- 自スロットに Operation.PayloadItemID を設定
- SourceSlot を空に
- Return: true (成功扱い)
[OnDragEnter] / [OnDragLeave] でハイライト切り替え
4位置の反映: 3 つの方法
| 方法 | 使い所 |
|---|---|
SetPositionInViewport(NewPos) | UserWidget 全体を動かす(Add to Viewport で追加した物) |
Set Render Translation | 軽量な見た目だけの移動。レイアウト計算非対象 |
親 Canvas Panel Slot の Position | Canvas Panel 配下の子の位置移動 |
5マウス位置の取得 API
// PlayerController から
APlayerController* PC = GetWorld()->GetFirstPlayerController();
float MouseX, MouseY;
PC->GetMousePosition(MouseX, MouseY);
// ビューポート座標 (UMG 用、DPI スケール考慮)
FVector2D MousePos;
UWidgetLayoutLibrary::GetMousePositionOnViewport(this, MousePos);
// DPI スケールも考慮
FVector2D ScaledMousePos =
UWidgetLayoutLibrary::GetMousePositionScaledByDPI(PC);
// Geometry の Local 座標
FVector2D LocalPos = InGeometry.AbsoluteToLocal(
InMouseEvent.GetScreenSpacePosition());
6入力モードの設定(重要)
マウスイベントが UMG に届くには、PlayerController の入力モードが適切でないといけません:
// Pause メニュー等
FInputModeUIOnly UIOnly;
UIOnly.SetWidgetToFocus(MyWidget->TakeWidget());
PlayerController->SetInputMode(UIOnly);
PlayerController->bShowMouseCursor = true;
// HUD でゲーム入力もマウスも両方
FInputModeGameAndUI GameAndUI;
GameAndUI.SetWidgetToFocus(MyWidget->TakeWidget());
GameAndUI.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
GameAndUI.SetHideCursorDuringCapture(false);
PlayerController->SetInputMode(GameAndUI);
// 通常プレイ
FInputModeGameOnly GameOnly;
PlayerController->SetInputMode(GameOnly);
PlayerController->bShowMouseCursor = false;
7Z-Order とフォーカス
- 複数 Widget を重ねた時は
AddToViewport(ZOrder)の Z 値で前後関係指定 - Z が大きいほど手前
- Pause メニューは Z=1000 など大きめにすると HUD より前に出る
- マウスホバーが裏のウィジェットに届かないようにVisibility = Visible(または Self Hit Test Invisible でクリックを下に貫通)
8Visibility の使い分け
| Visibility | マウスイベント |
|---|---|
| Visible | 受け取る |
| Hit Test Invisible | 受け取らない(自分も子も) |
| Self Hit Test Invisible | 自分は受けないが子は受ける |
| Hidden | 非表示・受けない・スペース確保 |
| Collapsed | 非表示・受けない・スペース不要 |
9FAQ
Q: OnMouseButtonDown が呼ばれない
A: ① Visibility = Hit Test Invisible になっていないか、② 入力モードが Game Only になっていないか、③ 親ウィジェットが先にイベントを Handle していないか を確認。
Q: ドラッグ中にマウスがウィジェットから外れると追従が止まる
A: FReply::Handled().CaptureMouse(TakeWidget()) でマウスキャプチャを取得。終了時に ReleaseMouseCapture()。
Q: マウス座標がずれる
A: DPI スケールを考慮していない可能性。GetMousePositionScaledByDPI を使うか、SetPositionInViewport の第二引数 bRemoveDPIScale を false に。
子ページ
子ページはありません
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Git pushした変更の取消し|revert・履歴変更と保護の注意点 2026-10-15 23:49:01
- Gitでローカルを戻す前に|reset・restoreの違いと退避範囲 2026-10-15 23:49:01
- Git rebaseの使い方|対象範囲・競合解決・pushの判断 2026-10-15 22:50:59
- Git pullの使い方|取込み先・ff-only・競合とstashの注意点 2026-10-15 22:50:59
- Git pushの使い方|送信先・タグ・force-with-leaseの条件 2026-10-15 22:12:47
- Git remoteの設定・確認・削除|SSH URLとfetch/pushの違い 2026-10-15 22:12:47
- Gitリモートリポジトリの作成|初回push・既存履歴・mirrorの注意 2026-10-15 15:48:16
- Gitのuser.name・user.email設定|local/global・確認と過去履歴の注意 2026-10-15 15:30:07
- LinuxにGitをインストール|配布元・初期設定・TLSと認証の確認 2026-10-15 15:30:06
- Git導入と初回push|Linuxサーバー・Windows/macOS・SSH設定 2026-10-15 14:51:54
- Db2のCREATE INDEX|索引定義・INCLUDEと実行計画の確認 2026-10-15 14:10:22
- Db2の自動採番|IDENTITY・ID取得とRESTARTの注意点 2026-10-15 14:10:22
- 【DB2】特定スキーマの全テーブルの全カラム情報を取得する方法 2026-10-15 13:53:15
- Db2のシーケンスとIDENTITYの違い|採番とカタログの確認SQL 2026-10-15 13:53:15
- Db2で複数カラムをUPDATEする方法|SET・WHEREと更新前の値 2026-10-15 13:53:15