【Unity】重ねた2Dコライダをマウスで判別するアイデア

Home

重ねた2Dコライダをマウスで判別したい時、
以下のような悩みが出てきませんか?

  • コライダが重なっていると動作が不安定になる…
  • Physics2D.Raycastで取得するRaycastHit2D.colliderは取得できるコライダが1つしかないからどのコライダが反応しているか分からない…
  • かといって1つのGameObjectに2つ以上のコライダをアタッチするとエラーが出る…

本記事ではこのような悩みを解決するアイデアをご紹介します。

スポンサーリンク
スポンサーリンク

重ねた2Dコライダをマウスで判別するアイデア

私が考えたアイディアは以下の通りです。

  • コライダにz軸座標を設定する
  • 識別用スクリプトを作成してコライダにアタッチする
  • Physics2D.Raycastの返り値から識別用スクリプトをGetComponentし条件分岐する

順番にご説明します。

前提条件

説明の前に前提の条件を整理します。

  • カメラのProjectionがOrthographicであること
  • 2Dのゲームであること
  • カメラにx軸y軸の回転がないこと

この3点です。

カメラのProjectionをOrthographicにする理由は、
今回使用したCamera.ScreenToWorldPointを正常に動作させるためです。

2Dのゲームである理由は、
利用するメソッドがPhysics2D.Raycastであるためです。

カメラにx軸y軸の回転をなくす理由は、
重ねるコライダをz軸座標を調整して離すため、
座標によって位置が変わってしまうためです。

コライダにz軸座標を設定する

まず、コライダが重なっていると発生する不安定さを解消するために、
コライダにz軸座標を設定して離します。

例として、各コライダが子のGameObjectとして分離していると想定します。

そして、優先度の高いコライダのz軸座標をずらして配置します。

これで、優先度の高いコライダの場所へマウスを動かすと、
このコライダのみ反応するようになり、不安定な挙動がなくなります。

しかしこのままでは、コライダにマウスが当たったことは分かるものの、
後ろ側にあるコライダとの判別ができません
これを解決するために識別用スクリプトを作成します。

識別用スクリプトを作成してコライダにアタッチする

MonoBehaviourを継承した識別用スクリプトを作成します。

例として、以下の基底クラスを作りました。

public class IdentificationComponent : MonoBehaviour
{
    public int ID;
}

そして、これを継承したクラスを2つ作りました。
検証用なので中身は特に用意していません。

//ベースの板用
public class PanelIdentification: IdentificationComponent
{
}
//重ねる用
public class PointIdentification : IdentificationComponent
{
}

子のGameObjectはPanelとPointにリネームし、
それぞれPanelIdentificationPointIdentificationをアタッチしました。

なお、認識しやすいように、
Panelには白い板を、Pointには黒丸のTextureを貼り付けました。

Physics2D.Raycastの返り値から識別用スクリプトをGetComponentして条件分岐する

仕上げに取り掛かります。

Updateメソッドの中でPhysics2D.Raycastを実行し、
コライダの反応があった場合はRaycastHit2D.colliderから
IdentificationComponentGetComponentし、
最終的にSwitchで振り分けを行います。

        void Update()
        {
            var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            var hit = Physics2D.Raycast(ray.origin, ray.direction);

            if(hit.collider == null) { return; }

            var identification = hit.transform.GetComponent<IdentificationComponent>();

            switch (identification)
            {
                case PanelIdentification:
                    {
                        Debug.Log("Panel");
                        break;
                    }
                case PointIdentification:
                    {
                        Debug.Log("Point");
                        break;
                    }
            }         
        }

実行すると以下のようになりました。

GameObjectの名前で識別したほうが簡単な気がしますが、
ポリモーフィズムを利用したほうが拡張性や保守性が高くなると判断して、
このような実装にしました。

まとめ

いかがでしたか?

少し強引な方法ではありましたが、
何とか重ねたコライダを判別させることができました。

この記事が皆さんのお役に立てば幸いです。

皆さんの努力のサポート

この記事を書いた筆者はUnityの初心者向けレッスンを行っております。

  • 一人だと理解できない
  • モチベーションが続かない
  • スクールだと値段が高すぎる

このような悩みを持った方がいらっしゃればサポートしたいと思っております。
ご興味あれば覗いてみてください。

【Unity】初めてのゲーム制作サポートします。【プログラマ】【未経験OK】|あなただけのパーソナルメンターを(MENTA)
プラン概要Unityを使ってゲームを作れるまでサポートいたします。まったくの未経験の方でも、ある程度やってきた方でもOKです!優しく丁寧に受け答えしますので、よろしくおねがいします!!メンター情報現役....

スポンサーリンク
スポンサーリンク
HomeUnity
むたこなをフォローする
むたこなブログ

コメント

タイトルとURLをコピーしました