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

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

ただいまの
回答率

90.34%

  • Unity

    4409questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity2D

    976questions

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 264

ToToMonjya

score 2

 前提・実現したいこと

下記の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/

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • negitama

    2018/06/04 17:58

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

    キャンセル

  • ToToMonjya

    2018/06/04 19:55

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

    キャンセル

回答 1

checkベストアンサー

0

 回答1

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

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

 回答2

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

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

using UnityEngine;

// Cellを識別するID
public class CellId : MonoBehaviour
{
    public string cellId;
}

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

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

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


これでOKです。

参考動画
イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/04 19:58

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

    キャンセル

  • 2018/06/04 21:46

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

    キャンセル

  • 2018/06/04 22:07

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

    キャンセル

  • 2018/06/04 22:12

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

    キャンセル

  • 2018/06/04 22:21

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

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Unity

    4409questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity2D

    976questions