しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

Unity で UI をドラッグ移動させる

※ これは 2020/10/30 時点の Unity 2020.1.11f1 の情報です

最新版では動作が異なる可能性がありますのでご注意ください

Blender の v2.90 の新機能の気になるものを確認できたので、Unity のお試しに戻り

今回は 新しい InputSystem を使って UI をマウスドラッグで移動できるようにしてみたい

新しい InputSystem は、Paclage Manager からインポートしたあと・・・

Input System パッケージ

Player Settings の Active Input Handling から選択できる(Unity Editor が再起動する)

InputSystem の切り替え

InputSystem の切り替えが終わったら、こんな感じで Main CameraEvent SystemUIGameObject とドラッグ移動させる ItemGameObjectを追加する

UI の Canvas

UI は上記のように CanvasCanvas ScalerGraphic Raycaster を追加した

Graphic Raycaster がないとドラッグが無視されるの注意!

ItemDraggable というあとで記述する Script と、Event TriggerCanvas GroupImage を追加

ドラッグできる Image

Event Trigger の部分はこんな感じで追加する

Event Trigger の追加

「Add New Event Type」ボタン押下後、追加するトリガーを選択する感じ

Draggable.cs は下記のように記述

using UnityEngine;
using UnityEngine.EventSystems;

[RequireComponent(typeof(CanvasGroup))]
public class Draggable : MonoBehaviour
{
    private Transform root;
    private Transform self;
    private CanvasGroup canvasGroup = null;

    public void Awake()
    {
        this.self = this.transform;
        this.root = this.self.parent;
        this.canvasGroup = this.GetComponent<CanvasGroup>();
    }

    public void OnBeginDrag(BaseEventData eventData)
    {
        // UI 機能を一時的無効化
        this.canvasGroup.blocksRaycasts = false;
    }

    public void OnDrag(BaseEventData eventData)
    {
        this.self.localPosition = GetLocalPosition(((PointerEventData)eventData).position, this.transform);
    }

    private static Vector3 GetLocalPosition(Vector3 position, Transform transform)
    {
        // 画面上の座標 (Screen Point) を RectTransform 上のローカル座標に変換
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            transform.parent.GetComponent<RectTransform>(),
            position,
            Camera.main,
            out var result);
        return new Vector3(result.x, result.y, 0);
    }

    public void OnEndDrag(BaseEventData eventData)
    {
        // UI 機能を復元
        this.canvasGroup.blocksRaycasts = true;
    }
}

重要なのは GetLocalPosition() で、Event Trigger から渡される座標を UI 用のローカル座標に変換するところ・・・transform.parent.GetComponent<RectTransform>() のところを transform.GetComponent<RectTransform>() にしてしまうとおかしくなる

これをやらないと思い通りの場所にならないので必須

さてお試し

ドラッグ移動

するっとドラッグ移動できた

こういうコンポーネントは Unity 標準で用意しておいてほしい・・・入力座標の変換とかわかりにくすぎる