i-school - 2Dタップシューティングゲーム 手順10
 以下の内容で順番に実装を進めていきます。

手順10 −コライダー同士の侵入判定の実装−
20.EnemyController スクリプトを修正し、エネミーのコライダーに対しての侵入判定処理を追加する
21.EnemyController スクリプトを修正し、侵入判定の際にエネミーとバレット両方を破壊する処理を追加する



 新しい学習内容は、以下の通りです。

 ・OnTriggerEnter2D メソッド
 ・Tag の設定
 ・処理のメソッド化



20.EnemyController スクリプトを修正し、エネミーのコライダーに対しての侵入判定処理を追加する

1.設計


 エネミーを作成しましたので、次は、エネミーとバレットとが接触するための処理を考えて、実装を行っていきます。

 いわゆる「当たり判定」と呼ばれるものです。
Unity には主に、コライダー同士が接触した際と、コライダーがもう片方のコライダーに侵入した際の2つの方法で当たり判定を用意し、確認することが出来ます。

 今回は2つ目の、コライダーがもう片方のコライダーに侵入した際の判定の方向で実装を行っていきます。
この処理は、Unity が用意している OnTriggerEnter2D メソッドを利用することで実装することが出来ます。

 この OnTriggerEnter2D メソッドを利用した判定を行うためには、バレットかエネミーのいずれかのコライダー、あるいは両方のコライダーの IsTrigger のチェックがオンになっている必要があります。
そのために、事前に、バレットのプレファブ・ゲームオブジェクトのコライダーと、エネミーのコライダーは、どちらも IsTrigger のチェックを入れてオンの状態にしてあります。
念のため、確認しておきましょう。


Bullet ゲームオブジェクト



EnemySet ゲーオブジェクト



 もしも IsTrigger にチェックが入っていなければ、ここで入れておいてください。


2.<OnTriggerEnter2D メソッド>


 Unityの用意している Collider クラスの持つメソッドの1つです。
このメソッドが記述されたスクリプトのアタッチされてるコライダーを持つゲームオブジェクト(キャラ)が、他のコライダーを持つゲームオブジェクトを通過した際に接触(侵入)判定を行うメソッドです。

 このスクリプトがアタッチされているゲームオブジェクトのコライダーの中に、侵入したゲームオブジェクトがある場合、
その情報を Collider 型で取得し、メソッド内で利用できる状態にしてくれます

 通常コライダーを持つオブジェクト同士は接触し停止しますが、いずれか片方のゲームオブジェクトのコライダーの IsTrigger のスイッチがオンになっている場合、
コライダーを持つゲームオブジェクトを通過(侵入)することができます。その際に、このメソッドが侵入判定を行います。

    // IsTriggerがオンのコライダーを持つゲームオブジェクトを通過した場合に呼び出される、コールバック・メソッド
    private void OnTriggerEnter2D(Collider2D other) {  // <= other は変数名なので、自由に名前を付けられる

        // 処理を書く

    // other 変数には侵入してきたゲームオブジェクトのコライダーの情報が入っているので、利用できる

    }

 侵入判定はコライダーであれば反応してしまうため、何も制限をかけないとバレット以外のゲームオブジェクトのコライダーにも反応してしまいます。
そのため、例えば、エネミーのゲームオブジェクトのコライダーが侵入した場合であっても侵入判定が発生してしまいます。

 そのため多くの場合は、Tag などの情報を利用して、侵入判定を行う対象となるゲームオブジェクトを制御して利用をします。


参考サイト
Unity公式スクリプトリファレンス
OnTriggerEnter
https://docs.unity3d.com/ja/current/ScriptReferenc...


3.EnemyController スクリプトを修正し、エネミーのコライダーにバレットのコライダーが侵入した際の判定処理を追加する


 設計を参考にしながら、 OnTriggerEnter2D メソッドを利用して侵入判定の処理を記述してみてください。
また画面上では侵入判定の確認が出来ませんので、OnTriggerEnter2D メソッド内に Debug.Log メソッドを用意して、Console ビューで挙動の確認を行いましょう。


EnemyController.cs


 スクリプトを修正したらセーブを行います。


4.ゲームを実行して動作を確認する


 スクリプトの修正が完成したら、ゲームを実行して侵入判定の確認を行います。
エネミーに対してバレットを発射してコライダー同士を接触させてください。
Console ビューに、Debug.Log メソッドで指定した "侵入したオブジェクト名 : Bullet(Clone)" と、
プレファブから生成されたバレットのゲームオブジェクトの名前が表示されれば侵入判定の制御は成功です。

 また侵入判定の名前のとおり、バレットのコライダーは、エネミーのコライダーを通過して突き抜けていくことが分かります。


<実行動画>
動画ファイルへのリンク


 もしもエネミーが移動していて、バレットを当てにくい場合には、EnemyController スクリプトにある、エネミーの移動の処理を一時コメントアウトしてください。
処理の先頭に半角スラッシュ2つを記述すればその行はコメントアウトされて、処理は実行されなくなります。

 デバッグを行う際には、特に記述がなくても、自分でやりやすい方法を見つけてそれを実践してみてください。
なおコメントアウトした場合には、デバッグが終了したらコメントアウトの解除を忘れないようにしましょう。



 無事に判定が取れました。ですがこのままですと、バレット以外のゲームオブジェクトに対しても侵入判定を行ってしまいます
試しに、Enemy ゲームオブジェクトを複製して、同じ位置に配置してゲームを実行してみてください。
Console ビューに侵入判定が表示されます。
 
 これは Tag を利用することで、特定のゲームオブジェクトとのみ侵入判定を行うようにする制御が可能です。
次の手順では、Tag の登録と設定を行い、その上で、EnemyController スクリプトを修正していきます。


5.バレットのプレファブ・ゲームオブジェクトに Tag の設定を行う


 Prefabs フォルダにある Bullet ゲームオブジェクトを選択し、インスペクターの一番上にある Open Prefab ボタンを押して編集モードにします。

 インスペクターの一番上のゲームオブジェクトの名前の左下に Tag という設定欄があります。


Tag



 現在は Untagged (Tag は未設定)の状態になっていますので、この部分をクリックしてください。
プルダウンメニューが開いて、登録されている Tag の中から1つを選択して登録できる状態になります。

 Bullet 用の Tag はまだ登録していませんので、プルダウンメニューの一番下にある Add Tags... ボタンをクリックしてください。
インスペクターの内容が、Tags and Layers という登録用の内容に切り替わります。



 Tag の登録は一番上の Tags 段で行います。右下にプラスボタンがありますので、押してください
Tag を登録してセーブを行うための小さいウインドウが開きますので Bullet と入力してセーブをしてください


Tag の登録



 このとき、この登録した文字列の情報を、スクリプトに記述する内容と合致させます。
大文字・小文字は区別されますので、スクリプトと Tag の書式を合わせることが大切です



 Tag の登録が終了したら再度、Bullet のプレファブ・ゲームオブジェクトを選択し Open Prefab して編集モードにします。
先ほどと同じように Tag の部分をクリックしてください。登録した Buulet の Tag が選択できるようになっていますので、登録します。

 これで Tag の設定は完了です。


プレファブの Buulet ゲームオブジェクト インスペクター画像



6.EnemyController スクリプトを修正し、侵入判定の際に、侵入したコライダーがバレットのコライダーかどうかを判定する処理を追加する


 OnTriggerEnter2D メソッドには Collier 型の引数があり、侵入してきたコライダーの情報を取得することが出来ます。
そのため、バレットのコライダーが侵入したら、という条件は、侵入してきたコライダーの情報を精査することが出来れば、条件として成立させることが出来ます。



 Collier 型の情報は広く活用することが出来ます。

 Collier 型からは、そのコライダーのアタッチされているゲームオブジェクトの情報を取得することが可能になっており、
ゲームオブジェクトの情報を取得することが出来れば、そこから Tag の情報を取得することが可能です。
つまり、侵入してきたコライダーの情報がわかれば、Tag の情報を取得して利用できることになります。


 以上の設計をふまえて、最初に OnTriggerEnter2D メソッドにロジックのコメントを書いてみましょう。

<コメントの参考例>
  // 侵入判定
  private void OnTriggerEnter2D(Collider2D col) {

   // 侵入したコライダーのゲームオブジェクトの Tag が Bullet なら(つまり、そのゲームオブジェクトは Bullet ゲームオブジェクトであると判定できる)
    // あるいは、Enemy ゲームオブジェクトのコライダーに、Bullet ゲームオブジェクトのコライダーが侵入していたら、とも書ける
            

     // 侵入判定の確認

    }

 どのようにすれば制御ができるようになるのか、考えて処理を記述してみましょう。
また Debug.Log メソッドで表示する内容も、Tag の名前を表示するように変更してみてください。


EnemyController.cs


 スクリプトを修正したら、忘れずにセーブしましょう。ショートカットキーを活用してください。


7.ゲームを実行して動作を確認する


 それではゲームを実行して、バレットとエネミーを接触させてみます。
Tag によって条件が判定されますので、Bullet Tag を設定している、バレットのゲームオブジェクトのみ条件を満たすことになります。
そのときは、Debug.Log メソッドが実行されて、"Bullet" という Tag の名前が Console ビューに表示されます。


<実行動画>
動画ファイルへのリンク


 もしも侵入した判定が行われずに、Console ビューに何も表示されない場合には、Tag の文字列と、スクリプトに記述した Tag 用の文字列が同じ文字列になっているかを確認します。
どちらかの先頭の文字が大文字になっているのであれば、対応する側の文字列も、先頭の文字が大文字でなければなりません。

 Tag の登録が Bullet であるなら、スクリプトに記述する文字列も Bullet にする必要があります。



 また Enemy ゲームオブジェクト同士も接触させて、侵入判定の結果を確認してみてください。
こちらも Tag による制御によって if 文の処理が実行されないため、if 文内の処理は実行されません。
そのため、Debug.Logメソッドは実行されず、Console ビューにもメッセージが表示されないはずです。


<実行動画>
動画ファイルへのリンク


 無事に制御ができましたら、次は、バレットに侵入されたエネミーと、バレット自体とを破壊する制御を追加していきます。


21.EnemyController スクリプトを修正し、侵入判定の際にエネミーとバレット両方を破壊する処理を追加する

1.設計


 侵入判定は OnTriggerEnter2D メソッドを実装することによって動作しています。
この処理の中に、バレットのコライダーがエネミーのコライダーに侵入したときに、どちらのゲームオブジェクトも破壊されるように制御を考えます。
 ゲームオブジェクトを破壊する処理は、Unity の用意している Destroy メソッドを実行することで実装できます。
Destroy メソッドでは、第1引数に指定したゲームオブジェクトを破壊することができます。

 いままでと同じように、ロジックを考える際には、日本語のコメントを書いておいて、処理を考えていきます。


<コメントの参考例>
  // 侵入判定
  private void OnTriggerEnter2D(Collider2D col) {

    // 侵入したコライダーのゲームオブジェクトの Tag が Bullet なら => Enemy ゲームオブジェクトのコライダーに、Bullet ゲームオブジェクトのコライダーが侵入していたら
        if (col.gameObject.tag == "Bullet") {
            
            // 侵入判定の確認
            Debug.Log("侵入したオブジェクトのタグ名 : " + col.gameObject.tag);


      // バレットのゲームオブジェクトを破壊する


            // エネミーのゲームオブジェクトを破壊する


        }
    }

 どのようにすれば制御ができるようになるのか、考えて処理を記述してみましょう。
バレットのゲームオブジェクトは、Debug.Log メソッドの引数の記述を参考してください。


2.EnemyController スクリプトを修正し、バレットがエネミーに接触したら破壊する処理を追加する


 以上の設計を元に、自分で考えて処理を書いてみましょう。
変数の値(中の情報)をしっかりと理解できているかどうかが、処理を記述する際のポイントになります。


EnemyController.cs


 スクリプトを修正したら、忘れずにセーブを行いましょう。


3.ゲームを実行して動作を確認する


 スクリプトの修正が完了したら、ゲームを実行して、バレットとエネミーにぶつけてみてください。
バレットとエネミーの両方のゲームオブジェクトが破壊されれば、破壊処理の制御成功です。

<実行動画>
動画ファイルへのリンク

 
 もしも上手く破壊されない場合には、Destroy メソッドの処理の場所や、引数にしている情報を見直してみてください。


4.<処理のメソッド化 −新しいメソッドを1つ作成し、OnTriggerEnter2D メソッド内の処理の内容の一部を移動するー>


 処理を書いた後には見直しを行います。

 OnTriggerEnter2D メソッド内に記述した処理が長くなってきたので、新しくメソッドを作成し、こちらの処理をそのメソッド内で処理するように
スクリプトの処理を作り直しましょう。

 デバッグとは異なり、処理の流れ自体に変更はないものの、処理をメソッド単位でまとめたり、見やすくして改善する手法をリファクタリングといいます。


    // 侵入判定
    private void OnTriggerEnter2D(Collider2D col) {

    // バレットが接触したら
        if (col.gameObject.tag == "Bullet") {
     

////*  ここから別のメソッドに処理を記述する  *////

       
            // 侵入判定の確認
            Debug.Log("侵入したオブジェクト名 : " + col.gameObject.tag);

            // バレットを破壊する
            Destroy(col.gameObject);

            // このゲームオブジェクトを破壊する
            Destroy(gameObject);


////*  ここまで  *////


        }
    }

 今回はこの範囲の処理を新しく作成するメソッド内に移動させて、この部分では、メソッドの呼び出し命令のみを記述するようにします。



 今回メソッドを作成して処理を行うためには1つ条件があります。それは、OnTriggerEnter2D メソッドにおいて取得している、侵入してきたオブジェクトの情報です。
この情報は引数の col 変数に代入されている情報であるため、別のメソッドではスコープの関係上利用できません

 そのため、別のメソッドでこの col 変数の情報を利用するには、新しく作成するメソッドにも引数を用意して、この情報を渡してあげる必要があります。

 用意する引数の型は、Collier 型、あるいは GameObject 型であれば渡しやすく、受け取ったメソッドでも利用しやすいです。

 実際に自分で処理を書いてみてから、こちらを確認してみてください。


EnemyController.cs


 いかがでしょうか。
メソッドに一連の処理がまとまっており、また、OnTriggerEnter2D メソッド内の処理もシンプルに見やすくなったと思います。

 処理自体は同じことを行っているのですが、このように書き方を変えるだけで、全体の見やすさも変わってきます。
覚えておいて、自分で処理を書いた際には、見直しをしていくようにしてください。


 以上でこの手順は終了です。

 次は 手順11 −バレットの情報を利用してエネミーを破壊する制御を実装− です。