i-school - パズルゲーム 発展15
 引き続き、ボム機能の制作をおこないます。

 この手順ではボム用のゲームオブジェクトの作成を行います。



<新しく学習する内容>
 ・Physics2D.OverlapCircleAll メソッド
 ・Physics2D.OverlapCircleNonAlloc メソッド
 ・MonoBehaviour.OnDrawGizmos メソッド
 ・Gizmos.DrawSphere メソッド



画像のインポート


 ボム用に任意の画像をインポートしてください。
干支と同じく、丸い形状の画像がいいでしょう。

 複数の画像が1枚にまとまっている場合には、Sprite Editor の機能を利用して分割しておいてください。


Eto プレハブを Unpack してボムのゲームオブジェクトとして活用する


 ボムのゲームオブジェクトも干支のゲームオブジェクトと同じように、Canvas 内に配置します。

 Canvas の EtoSetTran の子オブジェクトとして生成され、Image によってボム用の画像を持ちます。
他の干支と接触するようにコライダーを持っていますし、重力に合わせて落下するため、Rigidbody も持っています。

 つまり、干支とほとんど同じ機能を有していることが分かります。
こういったケースにおいては、同じものを最初から作るのではなく、すでにあるプレハブを活用することで効率的なゲームオブジェクトの制作が可能になります。

 早速 Eto プレハブを活用して、ボムのゲームオブジェクトを作成しましょう。



 ヒエラルキーの EtoSetTran ゲームオブジェクトの子オブジェクトとして Eto プレハブをドラッグアンドドロップして配置します。



ヒエラルキー画像



 その後、右クリックをしてメニューを表示し、Prefab → Unpack Completely を選択してプレハブ状態を解除(アンパック)し、通常のゲームオブジェクトに戻します





 この際、元の Eto プレハブはそのままプロジェクト内に残っていますので、心配はありません。



 アンパックした Eto ゲームオブジェクトの名前を Bomb に変更します。

 また、Image コンポーネントの Source Image の部分に、先ほどインポートしたボム用の画像をアサインして画像を変更します。
もしも画像の位置が上手く真ん中にこない場合には、子オブジェクトとして Image ゲームオブジェクトを新しく作成し、そちらで画像を設定してください。


<Image の位置がゲームオブジェクトの真ん中にくる場合>





 Image の位置がゲームオブジェクトの真ん中にこない場合、子オブジェクトの Image を使って画像を真ん中に合わせます。
この場合、親オブジェクトの Image は None にし、Alpha を 0 にして、透明な画像として配置しておきます。

 次に Button をアタッチしますので、Image コンポーネント自体は削除しないでください


親オブジェクト



親オブジェクト



Image は None にし、Alpha を 0 にして、透明な画像とする




子オブジェクト



子オブジェクト



 このように階層構造を活用することで、画像の位置だけを調整してゲームオブジェクトを作成することが出来ます。


Bomb ゲームオブジェクトに Button コンポーネントをアタッチする


 Bomb ゲームオブジェクトに Button コンポーネントをアタッチしてください。
子オブジェクトがある場合、親のゲームオブジェクトにアタッチします。





 特に設定は不要ですので、アタッチの確認を行ってください。


Bomb スクリプトを作成する


Bomb.cs

<= クリックすると開きます


 スクリプトを作成したセーブします。


<Physics2D.OverlapCircleAll / Physics2D.OverlapCircleNonAlloc メソッド>


 この機能は、指定した位置に、指定した半径のサイズで、一時的なコライダーを発生させる機能です。
ゲームオブジェクトにコライダーをアタッチせず、スクリプトによってコライダーを作るタイミングを指定することができる部分が大きなポイントです。

 2つのメソッドが用意されています。
このうち、Physics2D.OverlapCircleNonAlloc メソッドはいずれ廃止されることがアナウンスされています。
そのため今回は Physics2D.OverlapCircleAll メソッドの方で実装を行っています。


 // 範囲内の全ての敵のコライダーを取得
  Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, bombRadius);

 一時的に発生したコライダーを利用し、指定した位置の、指定した円形の範囲内にある、指定した Layer を持つゲームオブジェクトのコライダーをすべて取得し、配列に活用して戻します。


参考サイト
Unity 公式スクリプト・リファレンス
Physics2D.OverlapCircleAll()



 Physics2D.OverlapCircleAll メソッドではなく、Physics2D.OverlapCircleNonAlloc メソッドを利用した場合、処理は次のようになります。

        // OverlapCircleNonAlloc の場合(ただし、将来的になくなるため、非推奨)
        // 範囲内の全てのコライダーを取得するための配列を用意
        Collider2D[] hitColliders = new Collider2D[30];  // 10は仮の数値です。実際には適切な数値を設定してください。
        int numColliders = Physics2D.OverlapCircleNonAlloc(transform.position, radius, hitColliders);
        
        // 攻撃範囲内にコライダーが見つからない場合、処理しない
        if (numColliders == 0) {
            return;
        }

Unity 公式スクリプト・リファレンス
Physics2D.OverlapCircleNonAlloc()


<MonoBehaviour.OnDrawGizmos メソッド>


 Unity に用意されている、Scene ビュー内に Gizimo の情報を描画させるメソッドです。
描画先は Game ビューではなく、Scene ビューのみです。

 今回は Gizmos.DrawWireSphere メソッドを利用し、ワイヤーフレーム状の円を表示します。
第1引数と第2引数の部分に、Physics2D.OverlapCircleAll メソッドと同じ情報を指定しているので、
このメソッドによって発生するコライダーの位置とサイズを可視化しています。

 このように、メソッドに変数を上手く活用していくとデバッグしやすくなり、開発効率が上がります。


    private float radius;

    [SerializeField]
    private bool onGizmos = true;    // ギズモの機能のオンオフ切り替えを自分で作る


    private void OnDrawGizmos() {

        if (!onGizmos) {
            return;
        }
        
        // コライダーの可視化
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, radius);
    }

 下記のように変数を用意して切り替えることで、ギズモのオンオフが可能です。
デバッグの効率を考えて、適切な変数を用意していくことが大切です。


<確認動画>
動画ファイルへのリンク


参考サイト
Unity 公式スクリプト・リファレンス
MonoBehaviour.OnDrawGizmos()
Unity 公式スクリプト・リファレンス
Gizmos.DrawWireSphere


Unityを使った3Dゲームの作り方(かめくめ)様
UnityのGizmosを使ってシーンビューで視覚的なデバッグの補助をする
ねこじゃらシティ 様
【Unity】オブジェクトの情報をシーンビューにデバッグ表示する


Bomb ゲームオブジェクトに Bomb スクリプトをアタッチして、挙動のテストをする


 ヒエラルキーにある Bomb ゲームオブジェクトに、作成した Bomb スクリプトをアタッチします。

 インスペクターでの設定項目には OnGizmos 変数があり、最初は true になっています。
デバッグの際には OnDrawGizmos メソッドの内容を確認したいので、そのままで問題ありません。


インスペクター画像(OnGizmos 変数は false ですが、実際にはチェックして使ってください)



 ゲームを実行すると、最初からボムが配置された状態でゲームが動きます。

 まず、OnDrawGizmos メソッドが実行されているので、ボムの有効範囲が赤い円で可視化されています。
このサイズも調整可能ですので、まずはどの位のサイズになっているかを確認しておきます。
OnDrawGizmos メソッドはヒエラルキーにゲームオブジェクトがあれば、ゲーム実行時以外でも確認可能です。


OnDrawGizmos メソッドによるコライダー範囲の可視化



 なお、可視化したコライダーがゲームオブジェクトの中心から出ていない場合、Bomb ゲームオブジェクトの設定を見直す必要があります。



 その後、実際にボムのゲームオブジェクトをクリックして、Debug.Log("ボム実行"); のログが表示されて、ボムがゲーム画面から削除されるかを確認してください。
まだ周囲のゲームオブジェクトは削除されません。それは GameManager にある干支を削除する処理と Bomb スクリプト内の処理が連動していないためです。

 重要なことは、このようにして、処理を作っていく際には最後に1回の確認ではなく、各要素や機能を追加した段階ごとに、細かくテストを行っていくことです。
これを癖付けして、常に細かく問題がないかを検証していくように心がけてください。


Bomb ゲームオブジェクトをプレハブにして、ヒエラルキーから削除する


 動作の確認が終了したら、ヒエラルキーにある Bomb ゲームオブジェクトをプレハブにしてください。





 プレハブにしたら、ヒエラルキーにある Bomb ゲームオブジェクトは不要ですので削除してください。
EtoSetTran ゲームオブジェクトの子オブジェクトがない、初期の状態に戻して下さい。



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

 次は 発展16 です。

 最後に GameManager スクリプトを修正し、Bomb からの命令を受けて干支を削除する機能への繋ぎ込みを行います。
ボムの機能を完成させましょう。