teratail header banner
teratail header banner
質問するログイン新規登録
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

3回答

3059閲覧

Unity 2D プレイヤーに対して一定以上のインパクトが加わった時、ダメージを受ける処理をするにはどうすればいいか

sokmsss

総合スコア24

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2022/03/08 04:35

0

1

実現したいこと

現在、Unityで2Dの横スクロールアクションゲームを作成しています。

そこでゲームの処理として、オブジェクト間の衝突力によって処理を分岐させたいと思っています。実現したい具体的な処理としては、プレイヤーに対して一定以上のインパクトが加わった時、ダメージを受けるといった処理です。

調べたこと・分からないこと

衝突した時のインパクトを取得する方法について調べたところ、以下のようなコードを見つけました。 

C#

1 private void OnCollisionEnter(Collision collision) 2 { 3 float collisionForce = collision.impulse.magnitude / Time.fixedDeltaTime; 4 5 if(collisionForce > 200.0f) 6 { 7 Die(); 8 } 9 }

【Unity】衝突時のインパクト力を取得する方法
https://ymgsapo.com/2021/02/12/unity-impact-power/

上記のコードは、自分が実現したいものとほぼ同等なもので、Collision.impulseによってインパクトの取得と受け渡しを行っていますが、どうやら自分が調べた限りでは、Collision2Dには代替できる機能が存在しないということが分かりました。最終的にはこのような処理を行いたいのですが、結局インパクトの取得と受け渡し方法が分かりませんでした。

解決策やヒント等がありましたら、よろしくおねがいします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

Collision2D.contacts から衝突情報の配列が取れます。型は ContactPoint2D[] です。
ContactPoint2D.normalImpulse から衝突の力 (force) のスカラ量が取れます。衝突の力のベクトルは ContactPoint2D.normal から取れます。

でも 2D ゲームだったらここまでの物理計算はあまり必要ないと思います。単純に、ぶつかった速度 (velocity) とか、運動量または運動エネルギーなど、もっと簡単に求められるもので「作動するかしないか」を決めることが多いでしょう。

投稿2022/03/08 11:28

bboydaisuke

総合スコア5339

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sokmsss

2022/03/08 22:47 編集

回答ありがとうございます。 質問の内容からはややズレてしまうのですが、ご教授頂いたContactPoint2D.normalImpulseから、どの程度の衝撃までなら耐えれるかという簡易的な強度を作成してみました。強度についての知識は殆どないので、衝撃力を質量の0.8~1.15乗あたりで割って補正した値を、質量と比較して質量以上の値ならオブジェクトを破壊するというような感じで作成してみました(質量に関してはUseAutoMassで処理してます)。ただ、ゲーム中で見てみるとこの補正がやや不自然かなと感じてしまいます。このような処理の場合はどう補正をかけるべきなのか、または他に方法がありますでしょうか?
bboydaisuke

2022/03/08 23:03

マニュアルに書いてあったので回答しただけで、使ったことはないのでわかりません。
fana

2022/03/09 04:32 編集

> どの程度の衝撃までなら耐えれるか という話を考えるなら,真っ先に思いつく単純な話は if( 衝撃 > 耐えられる値 ){ 破壊 } という単純な閾値判定となるように思いますが,そうではなくて 質量の0.8乗で除すだとか,それを質量と比較するとかいう話はどうやって湧いて出てきたのか?: > 衝撃力を質量の0.8~1.15乗あたりで割って補正した値を、質量と比較して質量以上の値ならオブジェクトを破壊する っていうのは,どのような 考え/理屈/etc... からそのような処理とするに至ったのか? っていう話が無い状態で処理内容だけを概説したところで,他者には全く意味不明な話となるでしょう. そんな状態でその処理で行われている謎の「補正」をどうすればいいのか? と問われても誰も答えられないでしょう.
sokmsss

2022/03/09 05:08 編集

>>bboydaisuke 分かりましたありがとうございます。 >>fana 単純な操作(collisionから受け取れる値など)では取得できるパラメータに限りがあるため、耐久値を自身の質量と見立てて衝撃力を比較して判定するという処理を行いましたが、衝撃力に対して質量が小さすぎるケースが目立ったので補正をかけようとしています。何かいいアイディアがありますでしょうか?
fana

2022/03/09 05:23 編集

> 衝撃力に対して質量が小さすぎるケースが目立った 耐えて欲しい場面で耐えられないことが多い,という話であれば,「耐久値=質量」という話をやめればよいのではないでしょうか. (単純には,別途 耐久値 を持てばいい) 耐えられない場合の「オブジェクトを破壊する」というのが具体的に何が起こるという話なのかわかりませんが, 挙動が不自然と見える要因の一つとしては「当たりどころ」という観点もあるかも?とか思いました. (細いところは脆くて,分厚い所は頑丈,みたいな. 異なる耐久値を持つ複数の部分で物体が構成されている,というような扱いをすればそういうのも簡易的に表現できるかも.)
sokmsss

2022/03/09 06:04 編集

>>(単純には,別途 耐久値 を持てばいい) 単純に耐久値を定義する良いアイディアが浮かばなかったので質量、または質量の補正で代用しようとしています(良いアイディアがあればすぐにでも移行したいと思っています...。)。実際の応力をUnityで計算するのは取得できるパラメータの問題からかなり面倒な処理をしなくてはならなそうだと思ったので、このような処理に代替してみました。 しかし、明らかに違和感が生まれるくらいに物理法則から見ておかしい挙動になってしまったので悩んでいます。例えば、質量の小さなオブジェクトを自由落下させる時、地面と接触した衝撃(normalImpulse)でオブジェクトを破壊させようとした場合に、地面スレスレから落としてもオブジェクトが破壊されてしまうなどです。厳密でなくてもいいので、なるべく直感には反しない程度にしたいと思っています。 様々な面積・質量のオブジェクトを扱うので、出来れば動的に耐久値を設定したいと思っています。 >>耐えられない場合の「オブジェクトを破壊する」というのが具体的に何が起こる 文字通り、Destroy(this.gameObject)です。耐えられない場合はオブジェクトをDestroy()しようと思っています。
fana

2022/03/09 06:47 編集

Impulse とは 撃力 なのかな,と思って読んでいますが… > 地面スレスレから落としてもオブジェクトが破壊されてしまう すなわち,「落下速度が遅い状態でも計算される Impulse が小さいとは限らない」…なんてことになるものなのでしょうか?(← Impulse がどういう計算結果の値なのかを知らないので私には判断つかないところ) そもそもその値が直感に反しないものであるのか(例えばオブジェクトを落下させる高さに応じて大きさが変わっているのか)といったあたりは大丈夫なのでしょうか? (既に見られているだろうとは思いますが)判定に用いようとしている「衝撃」を可視化するなどしてみてはどうでしょうか. 「補正」に関してはそのパラメータに質量が入ってくること(0.8乗とかいうやつ)自体の正当性が私には判断つきません. (また,その補正結果と比較するのが質量である,という点も同様)
fana

2022/03/09 06:53 編集

※侵入量に応じた Penalty Force を発生させるような手法の場合,あるタイムステップにおける侵入量が速度と比例するとは限らないから,ある程度時間方向に積分する形で収集しないとならなかったような記憶. ここで用いられている Impulse ってのはどういう性質なのか? っていう. で,それはそれとして,回答で言われているように,運動エネルギーあたりで単純にやるのではダメなのだろうか?
guest

0

衝突側オブジェクトの衝突"直前"の速度(veloctiy)に質量(mass)をかければ、impulseと大体同じもの(impulseは力積なので厳密には違うのですが)が計算できるので、そちらで代用できると思います。
OnCollisionEnterだと衝突"後"で動きの止まったRigidbodyを取得してしまうので、OnTriggerEnter(別途Colliderが必要であればアタッチする)からRigidbodyを取得しましょう。

投稿2022/03/08 11:12

編集2022/03/08 11:23
UnchFullburst

総合スコア669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sokmsss

2022/03/08 21:15

回答ありがとうございます。
guest

0

collision.impulseの内部処理を確認すれば2Dに変換することは難しくないと思いますが、
そこまでしなくても衝突時のインパクトは質量と相対速度で決まると考えられるので、接触時に両者の質量と速度の差分に適当な係数を設けて掛け算でもすればよいかと思います。

投稿2022/03/08 10:50

YOshim

総合スコア1094

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sokmsss

2022/03/08 21:15

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問