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

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

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

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

Q&A

解決済

1回答

2715閲覧

Unity2D 特定のセルにだけドロップできるようにする方法

ToToMonjya

総合スコア8

Unity

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

0グッド

0クリップ

投稿2018/06/04 08:43

編集2018/06/04 12:25

前提・実現したいこと

下記のURLからダウンロードできるサンプルプロジェクトを参考にuGUIでのドラッグアンドドロップシステムを作成しているのですが
特定のセルにのみ特定のタイルをドロップできるようにするにはどうしたらいいでしょうか?

【追記】
サンプルプロジェクトを見ないとわからない点が多いと思うので、そちらを一度見ていただけると助かります…申し訳ありません…。

Tile.cs

using UnityEngine; using System.Collections; using System.Collections.Generic; public class Tile : MonoBehaviour { private Vector2 startingPosition; private List<Transform> touchingTiles; private Transform myParent; private AudioSource audSource; private void Awake() { startingPosition = transform.position; touchingTiles = new List<Transform>(); myParent = transform.parent; audSource = gameObject.GetComponent<AudioSource>(); } public void PickUp() { transform.localScale = new Vector3(1.1f,1.1f,1.1f); gameObject.GetComponent<SpriteRenderer>().sortingOrder = 1; } public void Drop() { transform.localScale = new Vector3(1, 1, 1); gameObject.GetComponent<SpriteRenderer>().sortingOrder = 0; Vector2 newPosition; if (touchingTiles.Count == 0) { transform.position = startingPosition; transform.parent = myParent; return; } var currentCell = touchingTiles[0]; if (touchingTiles.Count == 1) { newPosition = currentCell.position; } else { var distance = Vector2.Distance(transform.position, touchingTiles[0].position); foreach (Transform cell in touchingTiles) { if (Vector2.Distance(transform.position, cell.position) < distance) { currentCell = cell; distance = Vector2.Distance(transform.position, cell.position); } } newPosition = currentCell.position; } if (currentCell.childCount != 0) { transform.position = startingPosition; transform.parent = myParent; return; } else { transform.parent = currentCell; StartCoroutine(SlotIntoPlace(transform.position, newPosition)); } } void OnTriggerEnter2D(Collider2D other) { if (other.tag != "Cell") return; if (!touchingTiles.Contains(other.transform)) { touchingTiles.Add(other.transform); } } void OnTriggerExit2D(Collider2D other) { if (other.tag != "Cell") return; if (touchingTiles.Contains(other.transform)) { touchingTiles.Remove(other.transform); } } IEnumerator SlotIntoPlace(Vector2 startingPos, Vector2 endingPos) { float duration = 0.1f; float elapsedTime = 0; audSource.Play(); while (elapsedTime < duration) { transform.position = Vector2.Lerp(startingPos, endingPos, elapsedTime / duration); elapsedTime += Time.deltaTime; yield return new WaitForEndOfFrame(); } transform.position = endingPos; } }

InputManager.cs

using UnityEngine; using System.Collections; public class InputManager : MonoBehaviour { private bool draggingItem = false; private GameObject draggedObject; private Vector2 touchOffset; void Update() { if (HasInput) { DragOrPickUp(); } else { if (draggingItem) DropItem(); } } Vector2 CurrentTouchPosition { get { return Camera.main.ScreenToWorldPoint(Input.mousePosition); } } private void DragOrPickUp() { var inputPosition = CurrentTouchPosition; if (draggingItem) { draggedObject.transform.position = inputPosition + touchOffset; } else { var layerMask = 1 << 0; RaycastHit2D[] touches = Physics2D.RaycastAll(inputPosition, inputPosition, 0.5f, layerMask); if (touches.Length > 0) { var hit = touches[0]; if (hit.transform != null && hit.transform.tag == "Tile") { draggingItem = true; draggedObject = hit.transform.gameObject; touchOffset = (Vector2)hit.transform.position - inputPosition; hit.transform.GetComponent<Tile>().PickUp(); } } } } private bool HasInput { get { // returns true if either the mouse button is down or at least one touch is felt on the screen return Input.GetMouseButton(0); } } void DropItem() { draggingItem = false; draggedObject.transform.localScale = new Vector3(1, 1, 1); draggedObject.GetComponent<Tile>().Drop(); } }

サンプルプロジェクト

http://unity.grogansoft.com/word-game-drag-and-snap/

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

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

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

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

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

negitama

2018/06/04 08:58

サンプルのとおりには動かせて理解できたが、改変しても期待どおり動かない、ということでしょうか。貼り付けられているコードは改変したものですか?改変したものであれば、その箇所をコード内にコメントで示す等すると回答が得られやすいのではないでしょうか。不要な箇所まで解読するのは苦労しますので。
ToToMonjya

2018/06/04 10:55

サンプルプロジェクトでは全てのセルに全てのタイルが入れることが出来てしまうため、例えばセルAにタイルBだけしか入らないようにしたいのです。どこをどう改変していいのか分からないので、載せているコードはサンプルプロジェクトに入っているものから特に手を加えていません。恐らくSlotIntoPlaceの箇所にセルとタイルの種類を区別する記述をすればいいとは思うのですが、どう書けばいいのか分からないので…。
guest

回答1

0

ベストアンサー

回答1

質問者さんのコードは解読していませんが、uGUI要素のドラッグアンドドロップについては以前試したものがあるので、取り急ぎご参考まで。

[UI] ドラッグアンドドロップでUIのイメージを動かす : ねぎたまらぼ(Unity, ゲーム制作)
http://negi-lab.blog.jp/DragAndDrop

回答2

以下のようにすることで実現できました。

まずは下記スクリプトを作成し、各セルにアタッチします。インスペクターから ID の値をセットします。

C#

1using UnityEngine; 2 3// Cellを識別するID 4public class CellId : MonoBehaviour 5{ 6 public string cellId; 7}

Tile.cs は2か所を編集します。
まずは public string tileId; を追記して、タイルのIDをインスペクターからセットします。セルのIDと一致したときだけ置けるようにするためのものです。

次に、public void Drop() のなかの最後の if 文の条件を下記のように編集します。

C#

1if ( currentCell.childCount != 0 2 || tileId != currentCell.GetComponent<CellId> ()?.cellId )

これでOKです。

参考動画
イメージ説明

投稿2018/06/04 09:16

編集2018/06/04 12:45
negitama

総合スコア943

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

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

ToToMonjya

2018/06/04 10:58

ドラッグアンドドロップの方法はサンプルプロジェクトの方法でできています。 分からないのはドロップ先が受け取れる画像を制限する(セルAには画像1しかドロップできない、セルBには画像2…といったように)方法です。説明がうまく出来ずすみません…。
negitama

2018/06/04 12:46

回答2を追記したので確認してください。参考動画は「H」のタイルが特定のセルにだけスナップできるのを示したものです。
ToToMonjya

2018/06/04 13:07

ありがとうございます!確認してみたところ無事動作しました。 分かりにくい質問にもかかわらず、回答してくださり本当に助かりました。
negitama

2018/06/04 13:12

解決したようでよかったです。 (本来は何か自分でコード編集などを試してみた後で質問すべきだと思います。今後はそのようにされることをおすすめします。)
ToToMonjya

2018/06/04 13:21

そうですね、他力本願すぎました…反省します。 次回からこういったことがないよう、気をつけます! この度はご協力して下さり、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問