始めに
Unityでコライダーを複数もたせたオブジェクトを扱っているとき、
なぜか当たっていないはずのコライダーのイベントが発火するなんてことはないでしょうか。
それはRigidbodyコンポーネントが影響しているかもしれません。
例
キャラクターオブジェクト ←Rigidbody、Collider、被弾検出スクリプト
└視界オブジェクト ←Collider、他キャラクター検知スクリプト(←検知に使うため大きめのコライダーをセット)
上記のような構造のキャラクターに向かって攻撃コライダーを飛ばしたとします。(レイヤーはここでは考えない)
まず視界オブジェクトに当たった時点で、他キャラクター検知スクリプトが発火し、
そのあとキャラクターオブジェクトに当たった時点で、被弾検出スクリプトが発火するように思えます。
しかし実際には視界オブジェクトに当たった時点で、一気に被弾検出スクリプトまで発火してしまいます。
原因
こちらでも書かれておりますが、Rigidbodyは配下のコライダーをまとめて扱うという性質があり、
それによって子オブジェクトに付いているコライダーがまとめられているためです。
例の場合、キャラクターコライダーに視界コライダーも含まれた状態になってしまっているわけですね。
(正しい表現かはわかりませんが…。)
解消方法
レイヤーを適切に設定する
同一のRigidbody配下だとしてもレイヤーはしっかりと判定されるので、
それぞれでレイヤーを分けられるのであれば、それがベストでしょう。
例の場合、キャラクターオブジェクトと視界オブジェクトのレイヤーを分けて、視界オブジェクトと攻撃はヒットしないようにすればOKですね。
しかし、視界オブジェクトにおいても攻撃コライダーを検知したい場合もあります。
試してみたのですが、レイヤーを変えてもその両方がヒット有効なら両方のイベントが同時に発火してしまいました。
階層を並列にする
動かすのにRigidbodyを使っていないのであれば、階層を変えてしまう手があります。
同一Rigidbody配下でなくなれば当然発火しなくなります。
キャラクターオブジェクト(キャラクター動作はここで実施)
└キャラクター本体オブジェクト ←Rigidbody、Collider、被弾検出スクリプト
└視界オブジェクト ←Collider、他キャラクター検知スクリプト
じゃあ、キャラクターをRigidbodyで動かしている場合は…?
上の例だとキャラクター本体オブジェクトだけ独立して動いてしまいます。
子オブジェクト側にもRigidbodyを付ける
これしか思いつきませんでした。
こうすると子オブジェクトはそのRigidbodyで判定を独立できるようです。
Rigidbodyが別々に動いてしまわないようにするため、FixedJointで接続することになるでしょう。
キャラクターオブジェクト ←Rigidbody、Collider、被弾検出スクリプト
└視界オブジェクト ←Rigidbody、Collider、FixedJoint(キャラクターのRigidbodyと接続)、他キャラクター検知スクリプト
なんかゴチャゴチャとくっついてしまいますね…。もっとよい方法があればご教示ください。
終わりに
コリジョンイベントの発生には様々な条件がある分、意図しない動作をしたら色々とチェックしなければなりません。
今回の内容は知らないと結構ハマってしまうと思いますので、こちらに残させて頂きました。