【Unity】ドラックアンドドロップでCanvas/UIを動かす

当サイトで紹介する商品・サービス等の外部リンクは、アフィリエイト広告を含む場合があります。
スポンサーリンク
本記事を読むと以下の実行ができます

特定の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は、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。

ビックセール開催中(10月25日まで)
対象のコースが1800円から(最大95%OFF)

多彩な講座から自分に合った講座を探そう!

最大94%OFF

終了まで

時間

解説

  • 名前空間

「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のドラッグ&ドロップ可能

各UIをドラッグ&ドロップで移動

Canvas(UI全体)を動かせるようにしてしまうと、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などを使用すると、マウスを入力しているとき、離したときなどの処理を実装できます。

この記事を書いた人

プロフィール

アリッシア

                 

大学4年間で何か胸を張れるスキルを身に着けたくて当サイト運営を始めました。
現在、大学院に進学するか就職するか迷いながら勉強しています。
詳しいプロフィールはこちら

Contact icon

contact

X icon

X

Instagram icon

Instagram

Note icon

Note

スポンサーリンク
Unity
フォローする
タイトルとURLをコピーしました