この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: マウスを動かせるUIを作成する方法
SEOタイトル: Unreal Engine UMG マウス操作 UI 完全ガイド(ドラッグ&ドロップ / 入力モード / Z-Order)

この記事の要点
  • UMG ウィジェットをマウスでドラッグ移動させるには OnMouseButtonDown + OnMouseMove + OnMouseButtonUp の組み合わせ
  • 正式なドラッグ&ドロップは DetectDragIfPressed + DragDropOperation
  • 位置の反映は SetRenderTranslation または親 Canvas の Position プロパティ
  • マウス位置取得は GetMousePositionOnViewport または PlayerController の GetMousePosition
  • 入力モードを UI Only または Game and UI にしないとマウスイベントが UMG に届かない

2 種類のマウス操作 UI

Unreal Engine の UMG で「マウスで動かす UI」を作る方法は大きく 2 つあります:

シンプル移動正式ドラッグ&ドロップ
用途ウィジェット自身が動くUI 間でアイテム移動
主な APIOnMouseButtonDown/Move/UpDetectDragIfPressed + DragDropOperation
ペイロードなしOperation オブジェクトで運ぶ
視覚フィードバック自前Drag Visual ウィジェットで自動
難易度やや高

シンプル移動: ウィジェットをドラッグ

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();
}

正式なドラッグ&ドロップ(インベントリ等)

アイテムスロット間でアイコンをドラッグして移動する場合は、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] でハイライト切り替え

位置の反映: 3 つの方法

方法使い所
SetPositionInViewport(NewPos)UserWidget 全体を動かす(Add to Viewport で追加した物)
Set Render Translation軽量な見た目だけの移動。レイアウト計算非対象
親 Canvas Panel Slot の PositionCanvas Panel 配下の子の位置移動

マウス位置の取得 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());

入力モードの設定(重要)

マウスイベントが 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;

Z-Order とフォーカス

  • 複数 Widget を重ねた時は AddToViewport(ZOrder) の Z 値で前後関係指定
  • Z が大きいほど手前
  • Pause メニューは Z=1000 など大きめにすると HUD より前に出る
  • マウスホバーが裏のウィジェットに届かないようにVisibility = Visible(または Self Hit Test Invisible でクリックを下に貫通)

Visibility の使い分け

Visibilityマウスイベント
Visible受け取る
Hit Test Invisible受け取らない(自分も子も)
Self Hit Test Invisible自分は受けないが子は受ける
Hidden非表示・受けない・スペース確保
Collapsed非表示・受けない・スペース不要

FAQ

Q: OnMouseButtonDown が呼ばれない
A: ① Visibility = Hit Test Invisible になっていないか、② 入力モードが Game Only になっていないか、③ 親ウィジェットが先にイベントを Handle していないか を確認。

Q: ドラッグ中にマウスがウィジェットから外れると追従が止まる
A: FReply::Handled().CaptureMouse(TakeWidget()) でマウスキャプチャを取得。終了時に ReleaseMouseCapture()

Q: マウス座標がずれる
A: DPI スケールを考慮していない可能性。GetMousePositionScaledByDPI を使うか、SetPositionInViewport の第二引数 bRemoveDPIScale を false に。