しっぽを追いかけて

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

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

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

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

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

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

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

スポンサードリンク

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

f:id:matatabi_ux:20201030220008p:plain
Input System パッケージ

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

f:id:matatabi_ux:20201030213619p:plain
InputSystem の切り替え

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

f:id:matatabi_ux:20201030223541p:plain
UI の Canvas

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

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

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

f:id:matatabi_ux:20201030224035p:plain
ドラッグできる Image

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

f:id:matatabi_ux:20201030224303p:plain
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>() にしてしまうとおかしくなる

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

さてお試し

f:id:matatabi_ux:20201030225422g:plain
ドラッグ移動

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

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

スポンサードリンク