特定のUIのみドラッグ&ドロップする。
ゲーム内では、プレイヤーはアイテムの装備やUI要素のカスタマイズ、
他にも建設やレベルデザインでオブジェクトを配置する際に、ドラッグ&ドロップ機能を利用します。
ドラッグ&ドロップの実装はゲーム開発の幅が広がり、
主にトランプやカードゲームなどで使用できるので習得したい機能の一つです。
本記事では、ゲームオブジェクトをドラッグ&ドロップを実装します。
- Unityでドラッグ&ドロップを使用したい。
- UIを画面に表示したい。
Canvas(UI全体)をドラッグ&ドロップで移動
Canvasは、ボタンやテキストなどUIを使用するときに表示されます。
ユーザーのマウス入力から稼働できるようにします。
Hierarchyウィンドウから「UI」で1つ選択します。
本製作では、Imageを例とします。
ソースコード
using UnityEngine;
using UnityEngine.EventSystems;
public class CanvasDragAndDrop : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
private RectTransform canvasRectTransform;
private bool isDragging = false;
private Vector2 offset;
private RectTransform draggedObject;
void Start()
{
canvasRectTransform = GetComponentInParent<Canvas>().GetComponent<RectTransform>();
}
public void OnPointerDown(PointerEventData eventData)
{
draggedObject = eventData.pointerCurrentRaycast.gameObject.GetComponent<RectTransform>();
if (draggedObject != null)
{
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, eventData.position, eventData.pressEventCamera, out localPointerPosition))
{
offset = draggedObject.anchoredPosition - localPointerPosition;
isDragging = true;
}
}
}
public void OnDrag(PointerEventData eventData)
{
if (isDragging && draggedObject != null)
{
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, eventData.position, eventData.pressEventCamera, out localPointerPosition))
{
draggedObject.anchoredPosition = localPointerPosition + offset;
}
Debug.Log(localPointerPosition);
}
}
public void OnPointerUp(PointerEventData eventData)
{
isDragging = false;
draggedObject = null;
}
}
UdemyでUnityを学習
Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。
- 【Unity C# ゲーム開発超入門】7つのミニゲームを作っておぼえる!UnityとC#講座
Unityで頻出の機能を実際のゲーム作りで学習。
何か作りたい、今後の開発で役立てたい初心者におすすめ
- 【Unity C# ゲーム開発初心者レベルアップ】7つのトランプゲームを作っておぼえる!UnityとC#講座
トランプやボードゲーム作りに特化している講座。
テーブルゲームを作りたい人におすすめ。
- 【全行程を網羅!最初に学びたい総合学習】Unityワールド制作講座
Unityワールド制作の全工程を学習できる講座。
RPGを作りたい人におすすめ。
- Unity ゲーム開発:インディーゲームクリエイターが教える C#の基礎からゲームリリースまで【スタジオしまづ】
C#の文法やApp StoreとGoogle Playへゲームをリリース方法を解説。
ゲームを出品したい人におすすめ。
解説
- 名前空間
「UnityEngine」:Unityエンジンの基本機能にアクセスするために必要です。RectTransform、Canvasなど、UI要素を操作するために使用されます。
「UnityEngine.EventSystems」:UnityのUIイベントシステムを構成するインターフェースやクラスが含まれていて、ユーザーの操作(ドラッグ、クリックなど)に応答するためのインターフェース(IPointerDownHandler, IDragHandler, IPointerUpHandler)が対象です。
インターフェースを実装しており、UI要素のドラッグ&ドロップ機能を実現しています。
- フィールド(メンバ変数)
「canvasRectTransform」:このスクリプトがアタッチされているCanvasのRectTransformを保持します。UI要素の位置計算に使用されます。
「isDragging」:現在オブジェクトがドラッグされているかどうかを示すフラグです。
「offset」:ドラッグ開始時のオブジェクトのローカル座標とマウスの位置との差分を保持します。これにより、オブジェクトが正確にマウスの移動に追従します。
「draggedObject」:現在ドラッグされているUI要素のRectTransformを保持します。
- Startメソッド
親のCanvasからRectTransformを取得して、canvasRectTransformに保存します。
- OnPointerDownメソッド
マウスボタンが押されたときに呼び出されるメソッド(IPointerDownHandlerインターフェースの実装)。
ドラッグされたUI要素のRectTransformを取得し、ドラッグ開始時のオフセットを計算して保存します。
- OnDragメソッド
マウスがドラッグされている間に呼び出されるメソッド(IDragHandlerインターフェースの実装)。
現在のマウスの位置をCanvas内のローカル座標に変換し、オフセットを加算してUI要素を移動させます。
- OnPointerUpメソッド
マウスボタンが離されたときに呼び出されるメソッド(IPointerUpHandlerインターフェースの実装)。
ドラッグフラグをfalseに設定し、ドラッグされているUI要素の参照をクリアします。
実装
スクリプトをCanvasにアタッチします。
これにより、子オブジェクトのUIはドラッグ&ドロップの対象になります。
各UIをドラッグ&ドロップで移動
Canvas(UI全体)を動かせるようにしてしまうと、UIボタンやテキストなど全てのオブジェクトが対象になってしまいます。
したがって、動かしたいオブジェクトのみ処理できるようにします。
ソースコード
using UnityEngine;
using UnityEngine.EventSystems;
public class UIDragAndDrop : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
private RectTransform rectTransform;
private Canvas canvas;
private CanvasGroup canvasGroup;
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
canvas = GetComponentInParent<Canvas>();
canvasGroup = GetComponent<CanvasGroup>();
}
public void OnBeginDrag(PointerEventData eventData)
{
if (canvasGroup != null)
{
canvasGroup.alpha = 0.6f; // 半透明にする
canvasGroup.blocksRaycasts = false; // ドラッグ中にレイキャストを無効にする
}
}
public void OnDrag(PointerEventData eventData)
{
if (canvas != null)
{
rectTransform.anchoredPosition += eventData.delta / canvas.scaleFactor;
}
}
public void OnEndDrag(PointerEventData eventData)
{
if (canvasGroup != null)
{
canvasGroup.alpha = 1f; // 元に戻す
canvasGroup.blocksRaycasts = true; // レイキャストを有効に戻す
}
}
}
解説
- フィールド(メンバ変数)
「rectTransform」:UI要素のRectTransformを保持します。RectTransformは、UI要素の位置やサイズを管理するために使用されます。
「canvas」:UI要素が含まれているCanvasを保持します。
CanvasはUI要素の表示とレイアウトを管理するためのコンテナです。
「canvasGroup」:UI要素にアタッチされているCanvasGroupを保持します。
CanvasGroupは、UI要素の透明度やレイキャストのブロックなどの設定を管理します。
- OnBeginDragメソッド
ドラッグ操作が開始されたときに呼び出されます(IBeginDragHandlerインターフェースの実装)。
もしCanvasGroupがアタッチされている場合、そのCanvasGroupの透明度を0.6に設定して半透明にし、レイキャストを無効にします。
ドラッグ中に他のUI要素によるクリックなどが干渉しないようにします。
- OnDragメソッド
ドラッグ中に毎フレーム呼び出されます(IDragHandlerインターフェースの実装)。
ドラッグされているUI要素のRectTransformの位置を、マウスの移動に追従させます。
canvasのscaleFactorを使って、UIの拡大縮小に対応させています。
- OnEndDragメソッド
ドラッグ操作が終了したときに呼び出されます(IEndDragHandlerインターフェースの実装)。
CanvasGroupがアタッチされている場合、そのCanvasGroupの透明度を元に戻して(1に設定)、レイキャストを再度有効にします。
ドラッグが終了した後のUI要素の挙動を正常に戻します。
実装
動かしたいUI「Image」にスクリプトをアタッチします。
冒頭で紹介したように、正方形のオブジェクトはマウスで稼働しますが、テキストは操作されません。
まとめ
ドラッグ&ドロップにはIPointerDownHandler, IDragHandler, IPointerUpHandlerなどを使用すると、マウスを入力しているとき、離したときなどの処理を実装できます。