前書き
TopDown Engineの場合、プレイヤーが敵と接触したり、敵の攻撃に当たったりするときにダメージを発生させる方法として「DamageOnTouch」コンポーネントを使用してダメージを実装することができます。
参考にDamageOnTouchコンポーネントの設定については以下の記事にまとめています。
また、「プレイヤーと敵が接触した」、「敵の攻撃に当たった」っといったように接触判定をするためには「Collider」コンポーネントが必要になってきます。そのため、何かしらのダメージを発生させたい場合は「DamageOnTouch」と「Collider」が必ず必要になっています。
ただし、いろいろとDamageOnTouchを動かしていく中でColliderのIs Triggerが勝手に変わってしまうことが分かりました。
どんな事象が起こったのか?
敵にBoxCollider2DコンポーネントとDamageOnTouchコンポーネントを付与した状態で実行すると、”Is Trigger”パラメータが false から true に変更される事象がありました。以下の動画のように、プレイヤーと敵で当たり判定をしようとIs Triggerをfalseにした状態で実行しても、自動的にIs TriggerがTrueになってしまいます。
BoxCollider2Dの場合
Is Triggerが自動的にtrueになります。
CircleCollider2Dの場合
CircleCollider2Dでも動きを試しましたが、同様にIs Triggerが自動的にtrueになります。
CapsuleCollider2Dの場合
ただし、CapsuleCollider2DではIs Triggerはtrueになりませんでした。
- BoxCollider2DとCircleCollider2DのIs Triggerが勝手にtrueになる。
- CapsuleCollider2DではIs Triggerはtrueにならない。
という結果だったので、明らかに「DamageOnTouch」コンポーネント内部の処理でColliderのパラメータを変えていると思ったのでDamageOnTouchの実装を見ていきます。
DamageOnTouchの実装について
簡単に書くと初期化の段階で以下の処理がありました。
if (boxCollider2D != null)
{
boxCollider2D.isTrigger = true;
}
if (circleCollider2D != null)
{
circleCollider2D.isTrigger = true;
}
BoxCollider2DとCircleCollider2DのIs Triggerをtrueにする処理があり、CapsuleCollider2DのIs Triggerをtrueにする処理がない結果になります。
また実装をよく見てみるとオブジェクトに付与されているColliderをすべて見ているわけではなく、「最初に見つけたColliderのIs Triggerをtrueにする」処理になっていたため、同じコンポーネントで複数のColliderを付けてあげれば意図的にIs Triggerをture/falseに設定できそうです。
ColliderのIs Triggerをfalseのままにする方法
いろいろと場合分けが必要ですが、DamageOnTouchがある状態でIs Triggerをfalseのままにすることができるのは以下のパターンが考えられるかなと思います。
- パターン1:同じColliderを複数準備しておいて、Is Triggerをtrue/falseになるようにする。
- パターン2:CapsuleCollider2Dを使う
パターン1:同じColliderを複数準備
同じColliderを複数準備する場合(Is Triggerがfalseになる)
DamageOnTouchの仕様上、同じColliderがある場合は最初に取得できたColliderのIs Triggerをtrueにする処理になります。その作りを利用して同じColliderを2つ以上準備してあげれば、最初に見つかったCollider以外はIs Triggerをfalseのまま使うことができます。
以下の動画のようにBoxCollider2Dを2つ準備しました。上のBoxCollider2DのIs Triggerはtrueになりましたが、下のBoxCollider2DのIs Triggerはfalseのままです。この状態なら下のBoxCollider2Dと当たり判定が発生し、プレイヤーと敵が通過しないようになります。
同じColliderを複数準備しない場合(Is Triggerがfalseにならない)
ちなみに同じColliderを準備しない場合(BoxCollider2DとCircleCollider2Dを1つずつの場合)はDamageOnTouchの仕様上、以下の動画のように両方ともIs Triggerがtrueになってしまいます。
大事なことは「同じColliderを用意する」ということが分かります。
パターン2:CapsuleCollider2Dを使う
先ほども表示しましたが、DamageOnTouchの実装上ではCapsuleCollider2DのIs Triggerをtrueにする処理は入っていません。そのため、勝手にIs Triggerが変わることが嫌な場合はCapsuleCollider2Dを使っていただくのが直感的に分かりやすいかなと思います。
# ただし、今後TopDown Engineのソースコードに修正が入りもしかしたらCapsuleCollider2DにもIs Triggerがtrueになる処理が入る可能性があります。
注意!DamageOnTouchにはIsTriggerがtrueになっている必要がある!
ただし、ここからが注意になるのですが、DamageOnTouchを使うためにはIs Triggerがtrueになっている必要があります。
DamageOnTouchにあるパラメータ「Trigger Filter」の内容を見てみると
- OnTriggerEnter
- OnTriggerStay
- OnTriggerEnter2D
- OnTriggerStay2D
となっています。いずれも「Triggerが有効になっているとき」に判定が行われる設定になっているため、ColliderでIs Triggerがtrueになっているものが1つもない場合はDamageOnTouchは正しく動きません。
# 現状、Collision系(OnCollisionEnter2DやOnCollisionStay2Dなど)をDamageOnTouchでは使えないので、使いたい場合は自分で実装するしかなさそうです。
まとめ
今回はDamageOnTouchとColliderのIs Triggerの関係について紹介しました。
当時は自分もいろいろと調べたりして大分悩んだのですが、実装を見ると一目で分かるような内容だったので、疑問に思ったら実装を見てみるのが一番手っ取り早いかなと思います。
ちなみに、公式サイトのDamageOnTouchコンポーネントの使い方を見てみると
(2023年10月現在)
set its box collider to trigger
と注意書きがあるので、そもそもTriggerをfalseにして動かすことは想定してなかったのかなと思います。
コメント