プロジェクトでは、UI 要素を画面にドラッグアンドドロップすることで、プレイヤーがそれらとやり取りできるようにしたい場合があります。たとえば、インターフェースのレイアウトをカスタマイズする場合 (ヘルス バーやユニット フレームの配置など) や、インベントリ画面などのゲームプレイ システムとのインタラクション (アイテムの追加や削除など) などです。UMG では、DragAndDropOperation ノードを使ってこうしたタイプのインタラクションを作成し、インタラクションのメソッドに応じて、継承されたブループリント関数のいくつかをオーバーライドすることができます。
この例では、プレイヤーがマウスの左ボタンを使って画面上のヘルス バーをドラッグし、再配置する方法を示します。このガイドに沿って手順を完了すると、ビューポート内でドラッグして、新しい場所にドロップできる UI ウィジェットを作成できます。
1 - プロジェク設定
作業を開始する前に、プロジェクト設定の一環としてアセットをいくつか作成する必要があります。この例では、HUD で HealthBar 要素をドラッグアンドドロップできるようにします。 このためには、実際のヘルス バーをドラッグするのではなく、ヘルス バーと同じ形状の DragWidget を作成します。ここが、ヘルス バーをプログラミングするやり方とドラッグアンドドロップ機能の違う点です。
この操作ガイドでは、ブループリント サードパーソン テンプレート プロジェクトを使用します。
コンテンツ ブラウザ で、DragWidget、HealthBar、HUD という 3 つの ウィジェット ブループリント を作成します。
コンテンツ ブラウザ を右クリックして、新しい ブループリント クラス を作成します。
親クラスとして DragDropOperation クラスを選択し、作成したブループリント クラスに「WidgetDrag」と名前を付けます。
この特殊なブループリント クラスを使用することで、情報をドラッグアンドドロップ操作の一環としてパススルーできます。
WidgetDrag ブループリントを開き、WidgetReference という名前の User Widget 変数を作成します。[Instance Editable (インスタンス編集可能)] チェックボックスと [Expose on Spawn (スポーン時に公開)] チェックボックスをそれぞれオンにします。
これは、画面上でドラッグする UMG ウィジェットの保持に使用されます。
DragOffset という Vector 2D 変数を作成します。[Instance Editable (インスタンス編集可能)] チェックボックスと [Expose on Spawn (スポーン時に公開)] チェックボックスをそれぞれオンにします。
これにより、ウィジェットのドラッグアンドドロップを開始する地点からの位置がオフセットされます。
WidgetDrag ブループリントを コンパイル して 保存 します。
UI フォルダに移動して Drag Widget ブループリントを開きます。
ブループリント エディタ で [Graph (グラフ)] タブを選択します。
[My Blueprint (マイ ブループリント)] タブで、WidgetReference という名前の User Widget 変数を作成します。[Instance Editable (インスタンス編集可能)] チェックボックスと [Expose on Spawn (スポーン時に公開)] チェックボックスをそれぞれオンにします。
DragWidget ブループリントを コンパイル して 保存 します。
プロジェクトを設定したら、次にドラッグ可能な UI にする HealthBar Widget ブループリントでの作業を開始します。
2 - Health Bar ウィジェットを設定する
このステップでは、マウスの左ボタンが押されたことを判断し、スクリーン空間におけるその場所を格納します。また、DetectDragIfPressed ノードを使って、プレイヤーが指定されたキーでドラッグしているかを判断します。
HealthBar ウィジェット ブループリントを開き、[Hierarchy (階層)] パネルに移動します。
ボックスに Size Box と Progress Bar を追加します。Size Box の [Details (詳細)] パネルで、[Width Override (幅のオーバーライド)] を「500」に、[Height Override (高さのオーバーライド)] を「50」に設定します。
Progress Bar のスタイルを設定することもできます。[Hierarchy] パネルで Progress Bar を選択し、[Details] パネルで [Fill Color and Opacity (塗りつぶしの色と透明度)] の色を変更して、[Percent (パーセント)] を「1.0」に設定します。こうすることで、進捗バーに色を付けてそれを変更することができます。
プレビューを [Desired on Screen (オンスクリーン)] に設定します。
2.1 - On Mouse Button Down 関数をスクリプト処理する
このステップでは、プレイヤーがマウスの左ボタンをドラッグしているかどうかを判断します。
ブループリント エディタ で [Graph (グラフ)] タブを選択します。
[My Blueprint] パネルで、OnMouseButtonDown オーバーライドと OnDragDetected オーバーライドを追加します。これにより、それぞれのオーバーライドに対して イベント グラフ 内にタブが作成されます。
カスタム仕様の独自のスクリプトを呼び出すためにオーバーライドできる関数がいくつかあります。ここでは、マウス ボタンが押されたときと、ウィジェットのドラッグが検知された際の動作についていくつかのチェックを行います。
[OnMouseButtonDown] タブを選択します。OnMouseButtonDown ノードの My Geometry ピンからドラッグして、Absolute to Local ノードを作成します。
Mouse Event ピンからドラッグして Get Screen Space Position ノードを作成し、その Return Value を Absolute Coordinate ピンにつなげます。
これにより、マウス ボタンのボタン キー押下が記録されたスクリーン空間内の位置を取得して、Health Bar ウィジェットの絶対座標をローカル空間に変換します。その位置は変数として格納されるため、プレイヤーがウィジェット上で実際にクリックした位置とドロップした位置を判断することができます。
Absolute to Local ノードの Return Value を右クリックして [Promote to Variable (変数へ昇格)] を選択します。変数に「Drag Offset」と名前を付けます
クリックしてフルサイズで表示。
On Mouse Button Down ノードでエラーが発生しても大丈夫です。関数が完了するとエラーはなくなります。
グラフ内を 右クリック して、 Detect Drag if Pressed ノードを追加します。Drag Key を Left Mouse Button に設定します。
残りのピンの接続も完了させます。
Mouse Event を Pointer Event に接続します。
Detect Drag if Pressed と Return Node の Return Value ピン同士を接続します。
実行 ピンで 4 つのノードを接続します。
クリックしてフルサイズで表示。
これにより、プレイヤーがマウスの左ボタンをドラッグしているかどうかが判断され、その結果に応じて On Drag Detected スクリプトが開始されます。
HealthBar ブループリントを コンパイル して 保存 します。
2.2 - On Drag Detect 関数をスクリプト処理する
このステップでは、プレイヤーが実際に HealthBar を画面上でドラッグしている場合に何をするかを定義します。
[OnDragDetected] タブを選択します。OnDragDetected ノードから、Drag Widget ノードを右クリックして追加します。Class を Drag Widget に設定します。
Widget Reference ピンから Self ノードに接続します。その Return Value を「Dragged Widget」という名前の変数に 昇格 し、ピンを接続します。
これで、作成するドラッグ ウィジェットに既存の Health Bar ウィジェットへの参照が含まれるようになります。また、ダミーのドラッグ ウィジェットも変数に昇格するため、それに後でアクセスしたり、ウィジェットをドロップする際に画面から非表示にしたりできます。
右クリックして Drag & Drop Operation ノードを作成します。その Class を Widget Drag に、Pivot を Mouse Down に設定します。
Pivot では、ドラッグ操作を行っているポインタを基準としてドラッグされている場合に、Drag Widget Visual が表示される場所を定義します。
以下のノードを DragAndDropOperation ノードの各ピンに接続します。
Dragged Widget Set から Return Node までを 実行 ラインで接続する
Self から Widget Reference に接続する
Dragged Widget から Default Drag Visual に接続する
Drag Offset から Drag Offset に接続する
クリックしてフルサイズで表示。
上の画像では、参照するウィジェット ブループリントはどれか、そしてドラッグのビジュアルが何になるかを示し、ドラッグを開始するオフセットを提供しています。このノードにはデフォルトでオフセット ピンが含まれますが、独自の計算によって Mouse Button Down が押された際のドラッグの開始位置を定義しています。
HealthBar ブループリントを コンパイル して 保存 します。
次は、プレイヤーがマウスの左ボタンを放して OnDrop 関数を実行した際の動作を定義します。
3 - On Drop 関数を設定する
このステップでは、メインの HUD ウィジェット ブループリントを設定して、OnDrop 関数の実行時に生じる動作をオーバーライドします。
HUD ウィジェット ブループリントを開きます。
キャンバス パネル を [Palette (パレット)] パネルから [Hierarchy] パネルにドラッグします。その キャンバス パネル を選択し、[Details] パネルで [Visibility (可視性)] を [Visible (表示)] に設定します。
ドラッグ検知は Health Bar ウィジェット内でスクリプト処理されていますが、マウスの左ボタンが放されたときに、バーを HUD ウィジェット ブループリントにドロップするようにします。HUD でヒット検知を受け取るには、そのパネルを可視にする必要があります。
[Palette] パネルで、Health Bar ウィジェットを キャンバス パネル 追加します。
イベント グラフ グラフで、OnDrop 関数のオーバーライドを [My Blueprint] パネルから追加します。
OnDrop ノードの Operation からドラッグして Cast to WidgetDrag ノードを作成します。次に Get Widget Reference を追加し、As Widget Drag ピンを Widget Reference ノードと Drag Offset ノードに接続します。
これにより、OnDrop 関数の一環としてどの型の演算が実行されているかがチェックされます。Widget Drag の場合は、WidgetReference (ドラッグされているウィジェットとしてパススルー) と DragOffset (ドラッグの開始位置) を取得します。
My Geometry ピンから Absolute to Local ノードを作成します。Pointer Event ピンから GetScreenSpacePosition ノードを作成します。
クリックしてフルサイズで表示。
これは、マウスの左ボタンを放してウィジェットをドロップする、2D 空間における位置を表します。ここから DragOffset を差し引くことで、ウィジェットがドロップされた際にそのウィジェットを配置する位置を定義します。
Subtract ノードを追加して、Absolute to Local ノードの Return Value から DragOffset を差し引くように設定します。
クリックしてフルサイズで表示。
右クリックして、Remove from Parent ノード、Add to Viewport ノード、Set Position in Viewport ノードをそれぞれ追加します。実行 ピンをそれぞれ先述の順序で 3 つのモードに接続し、Set Position in Viewport ノードを Return Node につなげます。
以下のように接続または調整を加えます。
Widget Reference ピンを 3 つすべてのノードの Target ピンに接続します。
Vector2D - Vector 2D ノードから Return Value ピンを Position ピンに接続します。
Remove DPIScale のチェックを外します。
Return Value にチェックを入れます。
クリックしてフルサイズで表示。
Remove DPIScale をオフにして Return Value をオンにするのは、DPI スケーリング を取り除く必要がないためです。この関数は処理済みなので true を返します。このスクリプトでは、最初に既存の Health Bar ウィジェットを削除してから、Drag Offset を基準とした画面上の位置にこのウィジェットを再び追加します。
HUD ウィジェット ブループリントを コンパイル して 保存 します。
ドラッグしたウィジェットのドロップを処理するよう HUD が設定されて、ヘルス バーが表示されるようになりました。次は、ドラッグしたウィジェットをヘルス バーの形状を模倣するように設定し、キャラクター ブループリントに対してこの HUD をビューポートに追加するように指示します。
4 -Drag Widget をスクリプト処理する
このステップでは、ビューポート内でドラッグする視覚的ウィジェットである DragWidget を設定します。
DragWidget ウィジェット ブループリントを開きます。
[Hierarchy] パネルに Size Box ウィジェットと Border ウィジェットを追加します。SizeBox の名前を「WidgetSize」に変更し、その [is Variable] をオン (true) に設定します。[Width Override] と [Height Override] の両方のチェックボックスをオンにします。
この Size Box の幅と高さは、Health Bar ウィジェットのサイズを反映するように設定します。
Border を選択して [Brush Color (ブラシの色)] を 黒色 に設定し、透明感を与えるために [A (アルファ)] の値を「0.5」に設定します。
この例では、実際のヘルス バーを同じ場所に維持しながら、ドラッグのビジュアルとしてヘルス バーのシルエットを使用します。
ブループリント エディタ で [Graph (グラフ)] タブを選択します。
イベント グラフ 内で Event Construct からドラッグし、Cast to HealthBar ノードを作成します。ドラッグして Widget Reference を作成し、Object ピンに接続します。
As Health Bar ピンからドラッグし、Get Desired Size ノードを作成します。Return Value ピンを Break Vector 2D ノードへ接続します。
クリックしてフルサイズで表示。
これによってヘルス バーのサイズが決まり、Size Box を同じサイズに設定できます。オーバーライドは手動で入力することもできますが、ヘルス バーのサイズを変更する場合は、ここでもその変更を加える必要があります。
右クリックして Set Height Override ノードと Set Widget Override ノードを追加し、それぞれを Cast to HealthBar ノードへ接続します。次に、ドラッグして Widget Size ノードを作成します。
次のように各ピンを接続します。
Widget Size を両方の Target ピンに接続する
Break Vector 2D X を In Height Override に接続する
Break Vector 2D Y を In Width Override に接続する
クリックしてフルサイズで表示。
DragWidget ブループリントを コンパイル して 保存 します。
5 - HUD ウィジェットをビューポートに追加する
最後に、HUD Widget ブループリントを Character ブループリントのビューポートに追加し、マウス カーソルを有効にして、ドラッグしている場所がわかるようにします。
コンテンツ ブラウザ で「Content/ThirdPerson/Blueprints」までブラウズし、BP-ThirdPersonCharacter ブループリントを開きます。
Event Begin Play ノードから引き出して Create Widget ノードを追加し、Class を HUD に設定します。 Add to Viewport ノードを作成して SET Show Mouse Cursor に接続します。Get Player Controller ノードを追加し、Return Value を SET Target に接続します。
クリックしてフルサイズで表示。
BP_ThirdPersonCharacter ブループリントを コンパイル して 保存 します。
プレイ ボタンをクリックすると、ドラッグアンドドロップ ウィジェットを操作できます。
最終結果
エディタでプレイすると、左クリックして画面上のヘルス バーをドラッグし、新しい位置にドロップできます。
これは、ドラッグアンドドロップのプロセスを開始する際に必要な各要素を示した一例にすぎません。プレイヤーがウィジェットをセーフゾーン外にドラッグしないように、または他のウィジェットの上に重ねないようにするために、追加のチェックが必要になることもあります。