ドラッグ先のものを残す

せっかくだからドラッグ処理をもっと深掘りしようと思います。

いや、ちょっとだけ触って見てこのまま使わなかったら完全に忘れるからそのまとめ。

前回やったのは、ドラッグの動きを簡単に動かすこと。

Unity ドラッグを試す その1

ドラッグをするとちょっと自由に動きしすぎる(求める以上に自由に動ける)ので、やはり今回のアプリでは使わない予定。・・・Y軸固定とかすればいいけど。

とりあえず、やろう。

ドラッグ先のオブジェクトを残す

この状態だど、ドラッグするオブジェクトを丸ごと動かす状態。

今画像で動かして「1」をそのまま残してドラッグの動きをさせたい。参考にしたのは、こちら。

・記事名:uGUIでドラッグドロップ
・サイトリンク:http://qiita.com/ayumegu/items/c07594f408363f73008c

ドラッグ先のオブジェクトのコピーを作り

ドラッグ先のオブジェクトを残したい、つまり、ドラッグするものを新たに作り(コピーして)それを動かす

もしくは、ドラッグ先のオブジェクトの初期状態のコピーを作りを固定させてあげて、元のオブジェクトを動かすか。その2択かな?

私は、まずコピーを作りその子を動かすことにしました。(その方がDragEndの時破壊しやすい・・・?)

「1」のボタン(あれはボタンです)をドラッグすると、テキストオブジェクト「COPY!」が現れます。

結果物がこちら。

以下はそのソースC#です。

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

public class DragAndDrop: MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {

	private Transform canvasTran;
	private GameObject CopyTextObject;
	private Text CopyText;

	private Text thisText;
	private RectTransform thisTextRect;
	private Vector3 thisTextPosition;
	private Vector3 mousePosition;

	// Use this for initialization
	void Start () {
		canvasTran = transform.parent;
	}
	
	// Update is called once per frame
	void Update () {
		
	}

	// ドラック開始時
	public void OnBeginDrag(PointerEventData eventData)
	{
		Debug.Log("drag Start");

		//ドラッグ先テキスト
		thisText = this.GetComponentInChildren<Text> ();
		thisTextRect = GetComponent<RectTransform>();
		thisTextPosition = thisTextRect.localPosition;

		CreateDragObject ();

	}

	// ドラック中
	public void OnDrag(PointerEventData eventData)
	{
		Debug.Log("dragging");


		mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10);

		CopyText.transform.position = Camera.main.ScreenToWorldPoint (mousePosition);
	}

	// ドラック終了時
	public void OnEndDrag(PointerEventData eventData)
	{
		Debug.Log("dragEnd");

		Debug.Log("thisText = " + thisText.text);
		Debug.Log("copyText = " + CopyText.text);
	}

	private void CreateDragObject(){
		CopyTextObject = new GameObject ("copyText");
		CopyTextObject.transform.SetParent (canvasTran);
		//最前面表示
		CopyTextObject.transform.SetAsLastSibling ();
		CopyTextObject.transform.localScale = Vector3.one;

		CopyTextObject.transform.localPosition = thisTextPosition;

		CopyText = CopyTextObject.AddComponent<Text> ();

		CopyText.text = "Copy!";

		CopyText.font = Resources.FindObjectsOfTypeAll<Font>()[0];
		CopyText.fontSize = thisText.fontSize;
		CopyText.color = Color.white;
		CopyText.alignment = TextAnchor.MiddleCenter;

	}
}

噛み砕いて行こう

あくまで私の理解ですよ。間違いも多々あると思います。

さて、まず、宣言のところ。

	private Transform canvasTran;
	private GameObject CopyTextObject;
	private Text CopyText;

ゲームのオブジェクトを配置しているキャンバスと親子関係を持たせるための「canvasTran」。
ドラッグ先のコピー用テキストのゲームオブジェクトしての宣言のための「CopyTextObject」。
そのゲームオブジェクトにつけるコピー用テキスト「CopyText」。

初めは、「CopyText」だけでゲームオブジェクトとして成り立つかと思ったのですが、どうやら、ゲームオブジェクトの中のテキストという位置付けのよう。単体では表示されませんでした。

	private Text thisText;
	private RectTransform thisTextRect;
	private Vector3 thisTextPosition;

ドラッグ先の(コピー元の)テキスト情報を保持するためのもの。位置(ポジション?)情報などをコピー先に渡すためのもの。

	void Start () {
		canvasTran = transform.parent;
	}

スクリプトでオブジェクトを作成するのですが、他オブジェクトと同じくキャンバスさんの子供として扱って欲しいのです。なので、親子関係の情報を取って置きます。コピーオブジェクトにも持たせてやるから。

ドラッグのたびにやる必要はないので、スタートで取っておく。

・記事名:オブジェクトの親子関係のまとめ
・サイトリンク:http://qiita.com/hiroyuki7/items/95c66aee26115cf24a19

	// ドラック開始時
	public void OnBeginDrag(PointerEventData eventData)
	{
		Debug.Log("drag Start");

		//ドラッグ先テキスト
		thisText = this.GetComponentInChildren&lt;Text&gt; ();
		thisTextRect = GetComponent&lt;RectTransform&gt;();
		thisTextPosition = thisTextRect.localPosition;

		CreateDragObject ();

	}

ドラッグを開始したら、ドラッグ先のテキスト情報を取っておいて、コピーオブジェクト作成メソッドへ。

	private void CreateDragObject(){
		CopyTextObject = new GameObject ("copyText");
		CopyTextObject.transform.SetParent (canvasTran);
		//最前面表示
		CopyTextObject.transform.SetAsLastSibling ();
		CopyTextObject.transform.localScale = Vector3.one;

		CopyTextObject.transform.localPosition = thisTextPosition;

		CopyText = CopyTextObject.AddComponent&lt;Text&gt; ();

		CopyText.text = "Copy!";

		CopyText.font = Resources.FindObjectsOfTypeAll&lt;Font&gt;()[0];
		CopyText.fontSize = thisText.fontSize;
		CopyText.color = Color.white;
		CopyText.alignment = TextAnchor.MiddleCenter;

	}

ここでちょっと手こずった。やはりuGUIは偉大ですねぇ。スクリプトオブジェクト作るの面倒臭い。全部設定してやらないと出てこない。

初期状態の位置とか、どう表示させるか、フォントのサイズから種類から真ん中寄席の情報やら。

先に枠だけおいておいた「CopyTextObject」をチャット、ゲームオブジェクトして名前を与えて宣言してあげます。これによって、ドラッグを開始した時に初っ端はなかった「copyText」というオブジェクトがキャンバスにできます。

まだ、DragEnd処理で削除とかしないので、ドラッグが終わってもそのままオブジェクトは残っています。

	// ドラック中
	public void OnDrag(PointerEventData eventData)
	{
		Debug.Log("dragging");


		mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10);

		CopyText.transform.position = Camera.main.ScreenToWorldPoint (mousePosition);
	}

前回はドラッグ先オブジェクトにmousepositionを入れていたけど、それをCopyTextさんに設定すればこの状態に。

こんなものかな

コピーオブジェクトがずっと残りっぱなしだとうっとおしので、削除する処理をちらりと入れました。

	// ドラック終了時
	public void OnEndDrag(PointerEventData eventData)
	{
		Debug.Log("dragEnd");

		Destroy (CopyTextObject);
	}

これだけ。
あとは、コピーオブジェクトのテキストを、ドラッグ先のテキストにしてやりました。あとはカーソルのせいで文字がうまく見えないので大きくして見た。

結果はこう。

終わり。

ドロップ処理は、今のところ予定ない。