いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

UnityでUIオブジェクト(PanelやImageなど)をドラッグする

 作成中のゲームに簡単なヘルプ(遊び方の説明)をつける予定です。ある程度の量になってしまいます。スマホアプリですから画面は小さいので、大きなヘルプ画面をドラッグして見たい部分を見られるようにします。要するにスマホでサイトを見るような感じにしたいのです。

 実際の様子は次の通りです。白っぽいヘルプ画面(サンプルです)がゲーム画面に重なって見えています。これを右下にドラッグすると……
f:id:Inuosann:20210508154701p:plain:w250
下のようになります!!
f:id:Inuosann:20210508154743p:plain:w250

 ぼくはPanelにアイコンや説明文などを載せてヘルプにするつもりなので、Panelをドラッグできるようになるコードを紹介します。他のUIオブジェクトでも同じでしょう。次のスクリプトをドラッグしたいオブジェクトにアタッチするだけです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class HelpScript : MonoBehaviour, IBeginDragHandler, IDragHandler

{
    public Vector2 startPos;
    public Vector2 mouseStartPos;
//-----------------------------------
    void Start()
    {
        //使わない
    }
//-----------------------------------
    void Update()
    {
        //使わない
    }
    //-----------------------------------
//①
    public void OnBeginDrag(PointerEventData eventData)
    {
        //移動したいUIオブジェクトの最初の位置
        startPos = transform.position;
        //ドラッグを開始したときのマウスの位置
        mouseStartPos = eventData.position;
    }
    //-----------------------------------
//②
    public void OnDrag(PointerEventData eventData)
    {
        //ドラッグ中のUIオブジェクトの位置
        transform.position
                    = startPos + (eventData.position - mouseStartPos);
        //(eventData.position - mouseStartPos)は移動量
    }
}

 短いですし、プログラムを書く人なら何をしているか、意味は分かるはずです。全体を通して
transform.position
はオブジェクト(ここではPanel)の位置で、Vector2です。

public class HelpScript : MonoBehaviour, IBeginDragHandler, IDragHandler
として新しいクラスを作っています。

①オブジェクトがドラッグ開始されたときに
OnBeginDrag(PointerEventData eventData)
がコールされます。eventDataにはpositionメンバが含まれており、これはVector2で、ドラッグ開始時点のマウスポインタの位置です。しかし公式サイトを見ても「位置」としか書いておらず、原点も分かりません(誰か教えて……)。でも、原点がどこであろうが大丈夫です。このあと位置の変化量を加えるだけなので、原点の絶対的な位置は知らなくてもよいのです。

②public void OnDrag(PointerEventData eventData)
はドラッグ中、頻繁にコールされます。eventData.positionはやはりマウスポインタの位置です。コメントをつけておきましたが、マウスの移動量を最初のオブジェクトの位置に加えて、新しいオブジェクトの位置を求めています。

IBeginDragHandler
は、これを書いておかないとドラッグのスタート位置が正しく求められなくなり、動作がおかしくなります。エラーにはなりませんでしたが。
IDragHandler
も、書かなくてもエラーにはなりませんでしたが、ドラッグに反応しなくなります。

 ゴールが見えてきました。AdMobの導入がうまくいくか不安ですが、全部終わって公開したら大変な充実感を味わえると思います!