質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

681閲覧

Unity2Dでクリックしたオブジェクトの座標を取得したい

sumikko6210

総合スコア138

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2017/09/05 13:27

編集2017/09/12 08:39

イメージ説明

###前提・実現したいこと
Unity2Dでドラッグ&ドロップではめていくパズルゲームを作成中です。
現在、パズルが出てくるスポーンが一つだけなのですが、三つに増やしたいと考えております。
クリックした際、それぞれの元の座標を取得して、パズルがハマらなかった際に元の位置に戻したいです。

###該当のソースコード
Group.cs

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Group : MonoBehaviour 6{ 7 private Vector3 screenPoint; 8 private Vector3 offset; 9 10 //座標が範囲内であるか,Gridに値があるかどうかを判定 11 bool isValidGridPos() 12 { 13 foreach (Transform child in transform) 14 { 15 Vector2 v = Grid.roundVec2(child.position); 16 17 if (!Grid.insideBorder(v)) 18 return false; 19 20 if (Grid.grid[(int)v.x, (int)v.y] != null && 21 Grid.grid[(int)v.x, (int)v.y].parent != transform) 22 return false; 23 } 24 return true; 25 } 26 27 void updateGrid() 28 { 29 for (int y = 0; y < Grid.h; ++y) 30 for (int x = 0; x < Grid.w; ++x) 31 if (Grid.grid[x, y] != null) 32 if (Grid.grid[x, y].parent == transform) 33 Grid.grid[x, y] = null; 34 35 foreach (Transform child in transform) 36 { 37 Vector2 v = Grid.roundVec2(child.position); 38 Grid.grid[(int)v.x, (int)v.y] = child; 39 } 40 } 41 42 //オブジェクトをクリックする 43 void OnMouseDown() 44 { 45 // マウスカーソルは、スクリーン座標なので、 46 // 対象のオブジェクトもスクリーン座標に変換してから計算する。 47 48 // このオブジェクトの位置(transform.position)をスクリーン座標に変換。 49 screenPoint = Camera.main.WorldToScreenPoint(transform.position); 50 // ワールド座標上の、マウスカーソルと、対象の位置の差分。 51 offset = transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)); 52 53 54 } 55 56 //オブジェクトをドラッグする 57 void OnMouseDrag() 58 { 59 Vector3 currentScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z); 60 Vector3 currentPosition = Camera.main.ScreenToWorldPoint(currentScreenPoint) + this.offset; 61 transform.position = currentPosition; 62 } 63 64 //オブジェクトをドロップする 65 void OnMouseUp() 66 { 67 Vector3 currentScreenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z); 68 Vector3 currentPosition = Camera.main.ScreenToWorldPoint(currentScreenPoint) + this.offset; 69 70 //currentPositionが範囲内であるか,Gridに値があるかどうかを判定 71 if (isValidGridPos()) 72 { 73 transform.position = Grid.roundVec2(currentPosition); 74 Grid.deleteFullRows(); 75 Grid.deleteFullLines(); 76 77 //指定範囲内ではブロックの当たり判定を無くす 78 BoxCollider2D collider = GetComponent<BoxCollider2D>(); 79 collider.enabled = false; 80 81 //次のブロックを呼び出す 82 FindObjectOfType<Spawner>().spawnNext(); 83 84 85 } 86 else 87 { 88 //Spawnerオブジェクトの座標を取る 89 transform.position = GameObject.Find("Spawner").transform.position; 90 } 91 92 } 93 94 95 // Use this for initialization 96 void Start() 97 { 98 99 } 100 101 // Update is called once per frame 102 void Update() 103 { 104 if (isValidGridPos()) 105 { 106 // It's valid. Update grid. 107 updateGrid(); 108 } 109 } 110} 111

Grid.cs

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Grid: MonoBehaviour { 6 public static int w = 10; 7 public static int h = 10; 8 public static Transform[,] grid = new Transform[w, h]; 9 10 //座標を整数にする 11 public static Vector2 roundVec2(Vector2 v) 12 { 13 return new Vector2(Mathf.Round(v.x), 14 Mathf.Round(v.y)); 15 } 16 17 //指定範囲内かどうかを判定 18 public static bool insideBorder(Vector2 pos) 19 { 20 return ((int)pos.x >= 0 && 21 (int)pos.x < w && 22 (int)pos.y >= 0 && 23 (int)pos.y < h); 24 } 25 26 //横列を消去 27 public static void deleteRow(int y) 28 { 29 for(int x = 0; x < w; ++x) 30 { 31 Destroy(grid[x, y].gameObject); 32 grid[x, y] = null; 33 } 34 } 35 36 //縦列を消去 37 public static void deleteLine(int x) 38 { 39 for (int y = 0; y < h; ++y) 40 { 41 Destroy(grid[x, y].gameObject); 42 grid[x, y] = null; 43 } 44 } 45 46 //横列が埋まっているかどうかを判定 47 public static bool isRowFull(int y) 48 { 49 for (int x = 0; x < w; ++x) 50 if (grid[x, y] == null) 51 return false; 52 return true; 53 } 54 55 //縦列が埋まっているかどうかを判定 56 public static bool isLineFull(int x) 57 { 58 for (int y = 0; y < h; ++y) 59 if (grid[x, y] == null) 60 return false; 61 return true; 62 } 63 64 65 public static void deleteFullRows() 66 { 67 for(int y = 0; y < h; ++y){ 68 if (isRowFull(y)) 69 { 70 deleteRow(y); 71 } 72 } 73 } 74 75 public static void deleteFullLines() 76 { 77 for (int x = 0; x < w; ++x){ 78 if (isLineFull(x)) 79 { 80 deleteLine(x); 81 } 82 } 83 } 84} 85

Spawner.cs

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Spawner : MonoBehaviour 6{ 7 8 public GameObject[] groups; 9 public void spawnNext() 10 { 11 //配列の中をランダムで取り出す 12 int i = Random.Range(0, groups.Length); 13 14 //オブジェクトのインスタンスを作成 15 Instantiate(groups[i], 16 transform.position, 17 Quaternion.identity); 18 } 19 20 21 void Start() 22 { 23 spawnNext(); 24 } 25 26}

現在ドロップした瞬間にスポーンの位置に戻るようにしているため、複数個の場合、それぞれの位置に戻したいです。
rayを活用してみたのですが、ブロックは Instantiateで生成しているためか、反応しませんでした

回答よろしくお願いいたします。

###補足情報(言語/FW/ツール等のバージョンなど)
環境 Unity 5.6.2f1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

###Groupの処理では自身を動かすのではなくオブジェクトを動かすようにする。
[具体的な方法の提案]
・各オブジェクトのドラッグなどを簡単に判定するためにRaycasterを使った実装を紹介します。

[Raycasterを使う流れ]
0. カメラにPhysics 2D Raycasterをアタッチ
0. オブジェクトにCollider 2Dをアタッチ
0. 下記のようにIBeginDragHandlerなどを実装
0. オブジェクトにアタッチ(今回は自動でアタッチするように書いてますがほんとは始めからアタッチしてた方がいいかもしれません。とりあえず今回はspownObjというスクリプトを作ってコピしてassets内に保存してください)

※下記のコードが最適解という訳ではありません。一例としてごらんください。他にも伝えたいことはありますが、長くなるのでこのんで区切らせていただいます。

オブジェクトにアタッチするスクリプト

C#

1using System; 2using UnityEngine; 3using UnityEngine.EventSystems; 4 5/// <summary> 6/// スポーンするオブジェクトにアタッチ 7/// 本来なら共通処理を親クラスにした方が扱いやすいかもしれません。 8/// </summary> 9public class spownObj : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler 10{ 11 /// <summary> 12 /// ドラッグのスタート イベント 13 /// </summary> 14 public event Action<spownObj> OnBeginDragObj = delegate{}; 15 /// <summary> 16 /// ドラッグの中 イベント 17 /// </summary> 18 public event Action<spownObj> OnDragObj = delegate{}; 19 /// <summary> 20 /// ドラッグ完了 イベント 21 /// </summary> 22 public event Action<spownObj> OnEndDragObj = delegate{}; 23 24 /// <summary> 25 /// 初期の位置 26 /// </summary> 27 public Vector3 defaultPos{ get; private set; } 28 29 /// <summary> 30 /// このフラグでオブジェクトが動いていいかを判断する 31 /// </summary> 32 bool isMove = true; 33 public bool IsMove { get{ 34 return isMove; 35 } 36 set{ 37 isMove = value; 38 } 39 } 40 41 /// <summary> 42 /// トランスフォームをキャッシュ 43 /// 処理が軽くなるのでおすすめです。 44 /// </summary> 45 public Transform Tr; 46 47 48 /// <summary> 49 /// 外部にオブジェクトを生成するメソッドを公開 50 /// </summary> 51 public static spownObj Create(GameObject obj, Vector3 pos) 52 { 53 var go = Instantiate(obj, pos, Quaternion.identity) as GameObject; 54 var s = go.AddComponent<spownObj>(); 55 56 return s; 57 } 58 59 void Awake() 60 { 61 Tr = transform; 62 defaultPos = Tr.position; 63 } 64 65 /// <summary> 66 /// ドラッグのスタート 67 /// </summary> 68 public void OnBeginDrag(PointerEventData eventData) 69 { 70 if(isMove && OnBeginDragObj != null) OnBeginDragObj(this); 71 } 72 73 /// <summary> 74 /// ドラッグ中 75 /// </summary> 76 public void OnDrag(PointerEventData data) 77 { 78 if(isMove && OnDragObj != null) OnDragObj(this); 79 } 80 81 /// <summary> 82 /// ドラッグの終了 83 /// </summary> 84 public void OnEndDrag(PointerEventData eventData) 85 { 86 if(isMove && OnDragObj != null) OnEndDragObj(this); 87 } 88 89 /// <summary> 90 /// オブジェクトが削除される時にイベントも破棄する 91 /// </summary> 92 void OnDestroy() 93 { 94 OnBeginDragObj = null; 95 OnDragObj = null; 96 OnEndDragObj = null; 97 } 98}

操作する側

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class Group : MonoBehaviour 6{ 7 public GameObject[] groups; 8 9 List<spownObj> cacheObj = new List<spownObj>(); 10 11 void Start() 12 { 13 int i = Random.Range(0, groups.Length); 14 15 var spownScript = spownObj.Create(groups[i], transform.position); 16 //各種イベントを設定 17 spownScript.OnBeginDragObj += OnBeginDrag; 18 spownScript.OnDragObj += OnDrag; 19 spownScript.OnEndDragObj += OnEndDrag; 20 21 //オブジェクトをキャッシュ 22 cacheObj.Add(spownScript); 23 //後々使用したい場合はこんな感じで 24 cacheObj[0].IsMove = true; 25 } 26 27 /// <summary> 28 /// ドラッグのスタート 29 /// </summary> 30 public void OnBeginDrag(spownObj s) 31 { 32 Debug.Log("ドラッグスタート"); 33 //トランフォームからポジションを取得 34 Debug.Log(s.Tr.position); 35 //初期位置を取得 36 Debug.Log(s.defaultPos); 37 //オブジェクトの移動を制御 38 s.IsMove = true; 39 } 40 41 /// <summary> 42 /// ドラッグ中 43 /// </summary> 44 public void OnDrag(spownObj s) 45 { 46 Debug.Log("ドラッグ"); 47 } 48 49 /// <summary> 50 /// ドラッグの終了 51 /// </summary> 52 public void OnEndDrag(spownObj s) 53 { 54 Debug.Log("ドラッグ終了"); 55 } 56} 57

投稿2017/09/17 08:59

IShix

総合スコア1724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問