衝突解決


23

衝突をチェックする方法はよく知っていますが、衝突を適切に処理する方法はわかりません。

簡略化して、2つのオブジェクトが衝突した場合、速度の方向を変更するためにいくつかの計算を使用します。2つのオブジェクトを移動しない場合、それらは依然として重なり、速度が十分に大きくない場合、次の更新後にも衝突します。これにより、オブジェクトが互いにスタックする可能性があります。

しかし、2つのオブジェクトが重ならないように移動しようとするとどうなりますか。これは良いアイデアのように聞こえますが、3つ以上のオブジェクトがある場合、これは非常に複雑になることに気付きました。2つのオブジェクトを移動し、そのうちの1つが他のオブジェクトと衝突した場合、それらも移動する必要があり、壁などと衝突する可能性があります。

トップダウンの2Dゲームを考えていますが、それはそれとはあまり関係ないと思います。衝突は通常どのように処理されますか?

この質問はWoohに代わって尋ねられます


1
ゲームの種類を明確にできますか?「トップダウン2D」は、ゼルダスタイルのアクションアドベンチャーゲーム、垂直スクロールシューティングゲーム、ポケットビリヤードゲームなど、多くのことを意味します。これらはすべて、衝突を処理するための非常に異なる標準スタイルを持っています!
イアンシュライバー

2
それを明確にすることはできません。問題は衝突の結果として何が起こるかではなく、複数のオーバーラップの問題を処理することです。私はオブジェクトをお互いに跳ね返していることを知るだけで十分だと思い、この質問に答えるためにそれらが現実的に振る舞うことを望みます。
CiscoIPPhone

回答:


16

Daniel Kodicekは、このトピックについてプログラマー向けの数学と物理学で詳しく説明しています。

Kodicekは、自然な衝突解決を実現するために2つのことを行います。

  • 彼の衝突検出機能は、2つのオブジェクトが衝突する正確な時間を計算します。
  • 彼は衝突時に新しい速度を再計算するので、オブジェクトが重複することはありません。

Kodicekの衝突検出と解像度に基づくデモをアップロードしました。

更新: Kodicekの方法に非常に類似した衝突検出および解決アルゴリズムがあります。ソースコード。Kodicekのアルゴリズムは、実装方法がわずかに異なっており、はるかに詳細に説明されているため、私はまだKodicekの本をお勧めします。


1
デモリンクが壊れているようです。
ashes999

@ ashes999:リンクが修正されました!
レフティウム

それは円のためのアルゴリズムです。ボックスはどうですか?
アントンチキン

@AntonChikin:Kodicekの衝突解決アルゴリズムは、衝突点での質量、速度、法線の3つの入力のみを取ります。Kodicekは、衝突を検出するとき、常に衝突点で法線を計算します。彼は、ボックスが別のボックスに衝突するなど、さまざまなタイプの衝突検出について説明しています。その衝突検出アルゴリズムを衝突解決アルゴリズムにプラグインするだけです。完全な説明については、コディテックの本の8〜10章を参照してください。(回転物理学はより多くの数学を必要とすることに注意してください。これも本の後半でカバーされています...)
レフティウム

1
@ThomasHilbert:デモソースコードとWindows実行可能ファイルがleftium.com/asteroidで
レフティウム

6

オブジェクトが移動する前ではなく、移動する前に衝突をチェックするとどうなりますか?または、言い換えると、オブジェクトが衝突すると新しい位置を拒否し、その場合は古い位置を再利用しますか?

擬似コード:

  tmpPosition1 = Obj1.position
  tmpPosition2 = Obj2.position
  updatePosition(Obj1)
  updatePosition(Obj2)
  if collided(Obj1,Obj2) then
      updateVelocities( Obj1, Obj2 )
      Obj1.position = tmpPosition1
      Obj2.position = tmpPosition2
  endif

このように、更新ステップが十分に小さい場合、オブジェクトが衝突しようとしているときにオブジェクトが互いにぶつかり、プレイヤーは表現に奇妙なことに気付かないはずです。


1
これは非常に迷惑です。なぜなら、他のオブジェクトに触れた場合はすべて移動できないため、オブジェクトと平行に簡単に移動できないからです。
イッケ

あなたは、別途、xとyを解決しない限り
instantaphex

6

2つのオブジェクトが重なるたびに、それらが互いに近づいたり離れたりするかどうかを確認します。それらが互いに向かって移動する場合にのみ、衝突を行います。

ベクトル計算を使用するのは非常に簡単で、計算するだけです:

dot_product(B.position-A.position、A.velocity-B.velocity)

結果が正の場合、オブジェクトは互いに向かって移動します。


4

私は誤解しているかもしれませんが、あなたは2つの質問をしているように見えます:1.衝突解決を扱う一般的な方法は何ですか?あなたが探している用語は「インパルスベースのシミュレーション」であり、私よりも正義ができる

要約すると、質量と速度の積である運動量空間で物理シミュレーションをオイラーステップにしたいです(力に基づいたものを行わないでください、あなたのインテグレーターはとにかくそれを正しくしません)。

角度応答の場合、幸いなことに、最大および最小慣性モーメントは常に2つの直交軸(2D)に減らすことができます。これは、行列乗算が一般的に機能することを意味します。 2Dベクトル。

衝突がある場合、衝突点での線形モーメントと角モーメントに基づいて応答を計算します。相互貫通がある場合、適切なファッジファクターは、ペナルティ力(上記のように)を適用して2つのボディを分離することです。

この時点から、最大角運動量を制限するなどの異常な動作を制御するルールを追加して、トップのように回転しないようにしますが、これは良い出発点です。

可能な場合はシンプルにしてください。

  1. マルチボディ衝突の問題をどのように解決しますか

これを行う唯一の現実的な方法は、線形方程式のシステムと多くの解法です。それを行うための実用的な方法は、上記のようなシステムを使用し、物理学を時間の経過とともに自然に解決することです。

転がる、または動く表面に立っているなどのことを行うほとんどのゲームには、物理​​的な時間ステップに対応するために足が表面(または道路への車輪)に取り付けられたハイブリッドモデルがあります(これは相互貫通応答サイクルと動作しません)。

お役に立てれば。数学の例が必要な場合はお知らせください。


3

これが通常物理エンジンで解決される方法は、ペナルティフォースを適用することです。相互貫通後の剛体の移動は、剛体が高速で移動している場合は見栄えがよくありません(瞬間的なけいれん運動が表示されます)が、最初のステップとして、それを試して、要件に合うかどうかを確認する必要があります。

A penalty forceは、スプリングダンパーのように適用されます。この場合、リジッドボディを相互に貫通させるほどペナルティ力が増加し、後続のフレームでは減少します。スプリングと考えてください。2つのリジッドボディが相互貫通すると、それらはそれぞれ進行を弱める(つまり、相互貫通を防止する)目に見えないスプリングに遭遇しpenalty force、ボディが貫通しなくなるまで前述したものを適用します。

これは幅広いトピックですが、上記の情報があなたの出発点になることを願っています。


相互侵入を防ぐ代わりに、この方法はそれを可能にしますが、オブジェクトが圧縮されているように抵抗を提供しますか?
CiscoIPPhone

それは抵抗を提供します、はい、抵抗は身体が浸透しようとするほど増加します。実際には、十分に短いデルタ時間(たとえば10ミリ秒)がある場合、相互侵入は発生しません。ただし、この方法の本当の利点は、さまざまな理由で相互貫通したボディがある場合(位置が変更され、ネットワーク化された剛体であり、位置が修正された)、このテクニックなしではボディが分離されるためです徐々に分離するのではなく爆発します。
サマウルサ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.