UnityのuGUIとUniRxを使ってドラッグアンドドロップを実装してみました。
Sampleコード
DragAndDrop.cs
using UnityEngine;
using UniRx;
using UniRx.Triggers;
using System.Linq;
public class DragAndDrop : MonoBehaviour {
void Start () {
// 親CanvasのRectTransformを基準に利用する
var rectTransform = transform.root.gameObject.GetComponent<RectTransform>();
// RectTransformUtility.ScreenPointToLocalPointInRectangle用使い捨て変数
var tmpPosition = Vector2.zero;
// ObservableEventTriggerをオブジェクトに追加
ObservableEventTrigger trigger = gameObject.AddComponent<ObservableEventTrigger>();
// Dragイベントの登録
trigger.OnDragAsObservable()
// 発生するたびにマウスポジションを取得する。
.Select(_ => Input.mousePosition)
// ただしInput.mousePositionはWorld座標なのでそのままでは使えない。親CanvasのUI座標に変換する。
.Select(mousePosition => {
// ※注: 親CanvasのRender ModeをScreen Space Cameraにしている場合はこれでよいが、Screen Space Overlayの場合はまた別の記述になる。
// http://tsubakit1.hateblo.jp/entry/2016/03/01/020510 を参照。
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, mousePosition, Camera.main, out tmpPosition);
return tmpPosition;
})
// ついでにログを取ってみる
.Do(position => Debug.Log(string.Format("[Drag]Input.mousePosition.x: {0}, Input.mousePosition.y: {1}, Canvas.LocalPosition.x: {2}, Canvas.LocalPosition.y: {3}",
Input.mousePosition.x, Input.mousePosition.y, position.x, position.y)))
// 自分の位置をマウスのUI座標に。
.Subscribe(position => transform.localPosition = position)
// 自分が破壊されたらイベントも終了。
.AddTo(this);
// Drag終了イベント(つまりDrop)の登録
trigger.OnEndDragAsObservable()
// 発生したらマウスポジションを取得する。
.Select(_ => Input.mousePosition)
.Select(mousePosition => {
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, mousePosition, Camera.main, out tmpPosition);
return tmpPosition;
})
// ドロップされたらログを追加
.Subscribe(position => Debug.Log(string.Format("[Drop]Input.mousePosition.x: {0}, Input.mousePosition.y: {1}, Canvas.LocalPosition.x: {2}, Canvas.LocalPosition.y: {3}",
Input.mousePosition.x, Input.mousePosition.y, position.x, position.y)))
// 自分が破壊されたらイベントも終了。
.AddTo(this);
}
}
利用方法
- 親となるCanvasを用意し、Render Modeを"Screen Space - Camera"に設定します。
- ドラッグ&ドロップしたいUI系のgameObjectをCanvasの子オブジェクトに設定します。
- 上記のスクリプトをアタッチします。
- 起動して心行くまでグリグリします。
ドラッグ&ドロップが驚くほど簡単に実装できます。UniRx素晴らしすぎますね。