8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

#こんな感じになります
http://dividebyzero.sakura.ne.jp/DragAndDrop/index.html
※Unity5.2.2f1でWebGL出力 読み込みにそこそこ時間がかかるので注意。

#参考に視聴したもの
https://www.youtube.com/watch?v=c47QYgsJrWc
https://www.youtube.com/watch?v=bMuYUOIAdnc
https://www.youtube.com/watch?v=P66SSOzCqFU
https://www.youtube.com/watch?v=AM7wBz9azyU

まぁ、これらを見ると「意外と簡単だな?」ということはわかるわけなのですが。

#足りないと思ったのは

  • ドラッグしようとした瞬間、ポインタの位置に瞬間移動するのが気に食わない → ちゃんと相対位置取っておけば良いのでは。
  • 入れ替えアニメーションとか付けたい → 簡単なUpdateで出来るのでは。

ということで作ってみました。

#ドラッグされる方

DragObject.cs
using UnityEngine;
using UnityEngine.EventSystems;

[RequireComponent(typeof(CanvasGroup))]
public class DragObject : MonoBehaviour ,IDragHandler,IBeginDragHandler,IEndDragHandler
{
    public static DragObject dragObject;
    public Transform parentTransform;
    private Vector3 tapRefPosition;
    private CanvasGroup canvasGroup;
    private Transform canvasTransform;

    public CanvasGroup CanvasGroup { get { return canvasGroup ?? (canvasGroup = gameObject.AddComponent<CanvasGroup>()); }}
    public Transform CanvasTransform { get { return canvasTransform ?? (canvasTransform = GameObject.Find("Canvas").transform); } }

    public void OnBeginDrag(PointerEventData eventData)
    {
        tapRefPosition = (Vector2)transform.position - eventData.position;
        dragObject = this;
        parentTransform = transform.parent;
        transform.SetParent(CanvasTransform);
        CanvasGroup.blocksRaycasts = false;
        CanvasGroup.alpha = 0.5f;
    }

    public void OnDrag(PointerEventData eventData)
    {
        transform.position = Input.mousePosition + tapRefPosition;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (transform.parent == canvasTransform)
        {
            transform.SetParent(parentTransform);
        }
        dragObject = null;
        CanvasGroup.blocksRaycasts = true;
        CanvasGroup.alpha = 1.0f;
    }

    public void Update()
    {
        if (dragObject == null)
        {
            transform.localPosition -= transform.localPosition / 3.0f;
        }
    }
}

ポイントはonBeginDragでドラッグが始まる瞬間に、実際の位置とドラッグ開始位置の差分をtapRefPositionに確保している
tapRefPosition = (Vector2)transform.position - eventData.position;
と、OnDrag中はその差分tapRefPositionを加味して
transform.position = Input.mousePosition + tapRefPosition;
で実際にドラッグしている処理。

そして、Updateで、transform.localPositionを0にイーズアウトで近づける
transform.localPosition -= transform.localPosition / 3.0f;
です。

#ドロップされる方

DropTarget.cs
using UnityEngine;
using UnityEngine.EventSystems;

public class DropTarget : MonoBehaviour ,IDropHandler{
    public GameObject Item
    {
        get
        {
            if (transform.childCount > 0)
            {
                return transform.GetChild(0).gameObject;
            }
            return null;
        }
    }

    public void OnDrop(PointerEventData eventData)
    {
        if (Item == null)
        {
            DragObject.dragObject.transform.SetParent(transform);
        }
        else
        {
            Item.transform.SetParent(DragObject.dragObject.parentTransform);
            DragObject.dragObject.transform.SetParent(transform);
        }
    }
}

こちらは特筆することはなく、DropされたDropObjectのParentをセットしたり、交換したりしているだけです。
前述したDropObjectのtransform.localPosition -= transform.localPosition / 3.0f;の処理によって、Parentを差し替えるだけでアニメーション付きで移動をするのでラクチンです。

#足りてない所

  • Drag中のObjectは一番上に来て欲しいので、無理やり"Canvas"の名前でCanvas探してParentを変更している処理がありますが、名前変更してたら終わるね。 いくらでも手はあると思いますがぱっといい手が思いつかなかったのでペンディングしてます。

もっとuguiのノウハウが貯まるといいなぁ。

8
10
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?