Unity Physicsでのドラッグの仕組み

私の記事は、あるものを最初に見た(多くの人が知っている)人の喜びのようなものであることに気づき、別の記事を書くことにしました。 その理由は、 Rigidbodyコンポーネントに興味があるドラッグパラメーターです。 説明、特に数式-仕組み-はガイダンスを提供しません。 したがって、自分で理解する必要があります。

誰かが読むのが面倒な場合は、下にスクロールして、Unityでのドラッグを使用したスローダウンのアルゴリズムを見つけることができます。

Unityで物理に精通するとき、最初に教えられることは、 リジッドボディがオブジェクトの物理的特性の具体化であることです。 彼には、外界との相互作用を設定するパラメーターがいくつかあります。 実際には、動的オブジェクトにとって最も重要なのはmassです。 ニュートンの法則など…彼女はすべて直感的です。彼らは短時間力を加えました-彼らは衝動を受け、それに応じてオブジェクトの速度を変更しました。 私たちは長い間申請します。質量に応じて加速します。

さらに、 Rigidbodyには興味深いパラメーターdragがあります 。 開発者の言葉では、 ドラッグパラメーターオブジェクトのドラッグを設定ます。 彼らの言語では、 ドラッグは減速し、ブレーキをかけています。 他の説明はありません。 物理学とブレーキについて言えば、弾道学(空力、流体力学など)から何かが思い浮かびます。 おそらく、 ドラッグは速度の2乗に比例する要因です。 それは合理的です。 しかし。

単純な経験から、 Unityでは 、大きなドラッグ値を持つボディはまったく移動しないことがわかります。 重力はそれらに影響を与えません、それらをプッシュすることは不可能です。 しかし、同時に立ち上がる、つまり、速度の2乗はゼロになります。 したがって、ここではすべてがそれほど単純ではありません...または、逆に、すべてがそれほど複雑ではありません。 コンピューターゲームの物理学は迅速に計算する必要があります。つまり、実際の物理モデルに比べて単純化が可能です。 たとえば、相対論的な効果を持つゲームを実装するのは面白いでしょうが...

私が最初に尋ねた質問は、少なくともUnityの質量は質量のように振る舞うということです。 実験はそれを示した-はい。

質量/重力チェック
まず、単純なシーンで、平面上の5メートルの高さから質量1のボールを発射しました。 ボールが落ちた時間を観察できるように、飛行機のトリガーがタイマーを停止しました。

画像

推定落下時間は次のようになります。t = sqrt(2 * h / g )、ここでhは高さ、gは重力加速度です。 私たちの場合( h = 5m、 g = 9.81m / s ^ 2)t≈1.0096。
打ち上げの値は1.02で、これは望ましい値に近い値でした。

画像

組み込みの重力は良いです。 彼女が不正行為をしているかどうかを確認したいですか? Rigidbodyの重力をオフにし、代わりに手動で作用力を作成します。

void FixedUpdate() { rb.AddForce(0, -9.81f, 0); } 

結果は同じでした( t = 1.02)。 悪くない。

作用力については、いくつかの異なる意味が使用されました。 そして、常に有効力の変化( rb.AddForce(0、 xxx 、0); )により、計算されたものと一致する「落下」時間が変化しました。 そのため、力と質量の相互作用のモデルは非常に馴染みのあるニュートン型であることが判明しました。

さらに、組み込みの物理エンジンとシミュレートされたものをチェックして比較するために、2つのボールを作成しました。 1つは重力の影響下で動き、もう1つは台本の影響下で動きました。 そして今回は力がありませんでした。 速度の変更は、コード内で「手動」と見なされていました。

画像

まず、速度を落とすことなく、単純な落下をチェックする価値がありました( ドラッグ = 0)。 2番目のボールを移動するコードは非常に簡単でした。

 void FixedUpdate() { Vector3 newVelocity = rb.velocity + gForceVector * rb.mass * Time.deltaTime; rb.velocity = newVelocity; } 

rbは、 剛体球体のコンポーネントです。 gForceVector-重力ベクトル( 0、9.81、0 )。

画像

これまでのところ、すべてが同じです。

次に、左のボールのドラッグを増やしますdrag = 2)。 彼はよりゆっくりと落ち始めました:

画像

興味深い事実。 ドラッグパラメーターを大きな値(約50以上)に増やすと、ボールがまったく動かなかったという事実に至りました。 オブジェクトの質量の変化はこの事実にまったく影響を与えませんでした。これにより、 ドラッグパラメーターは運動学的である、つまり、力や運動量を考慮せずに位置、速度、加速度などに依存する(そして影響する)という考えに至りました。

他にドラッグが機能するアルゴリズムに影響を与えるものはありますか? おそらく物理学のリフレッシュレート。 これは、開発者にとって最善の動きを意味するものではありませんが。 しかし、冗談ではありません。 物理更新時間を0.005秒に変更します。

画像

まだ依存関係があります。 ただし、これらは計算上のエラーのようです。 物理学のリフレッシュレートをさらに増やしても、立ち下がり時間はそれほど変わりません。 ちなみに、これは開発者のコ​​ードのどこかに「 ... * Time.fixedDeltaTime 」のようなものがあるはずであることを意味します。

それでは、 ドラッグパラメータについて何を知っていますか? これは運動学的です(すべての力の作用後に考慮されます)。 Time.fixedDeltaTimeが (おそらく自分ではなく)乗算され、速度が低下します。 このような条件を思い付く最も簡単なことは、次のようなものです。

 void FixedUpdate() { Vector3 newVelocity = rb.velocity + gForceVector * rb.mass * Time.deltaTime; newVelocity = newVelocity - newVelocity*myDrag*Time.deltaTime; rb.velocity = newVelocity; } 

新しいアクションはかなり原始的です。1つの乗算と1つの減算(アクションがベクトルを使用して実行されるという事実に合わせて調整されます)。 ただし、どこかから始める必要があります。 便宜上、このコードを確認して、変数myDragに (2番目の球体のスクリプトから)最初の球体のdragパラメーターの値を自動的に割り当てます。

ドラッグ= 1
画像

ドラッグ= 3
画像

ドラッグ= 15
画像

ドラッグ= 50
画像

実際、ここでは両方のボールが動き始めませんでした。 私はただ待つのにうんざりしています。

だから、結果は私にとって予想外でした。 出発点として考えられていたプリミティブアルゴリズムは、そこからさらにプッシュしますが、最終点であることが判明しました。 ドラッグパラメーターを使用してUnityでスローダウンが考慮されるのはまさにそのようです。 一方、それはよりシンプルで、より高速であることを意味します(ランタイムの観点から)。

さらなる実験では、私のスクリプトと組み込み物理学との間に矛盾はほとんど示されませんでした。 ほぼ。 残っていることが1つありました。 ドラッグ = 100の場合、スクリプトによって移動された2番目のボールは、堂々と泳ぎました。

ドラッグ= 100
画像

一般的に、これはアルゴリズムに基づいて予想されるものでした。 ただし、Unityではこれは観察されません。 したがって、1つの簡単なコード変更が残っています。

 void FixedUpdate() { Vector3 newVelocity = rb.velocity + gForceVector * rb.mass * Time.deltaTime; newVelocity = newVelocity * Mathf.Clamp01(1f - myDrag*Time.deltaTime); rb.velocity = newVelocity; } 

現在、「ネガティブ」な動きは除外されており、 ユニティエンジンの力とブレーキの動作を完全に模倣しています。

ドラッグパラメーター自体の物理的な類似点は、選択するのに問題があります。 非線形摩擦(または非線形抵抗-より便利な方)を決定するということしか言えません。 同時に、アルゴリズム自体はシンプルで、おそらくすぐに実行されます。 したがって、物理モデルから特別な信頼性または高い予測可能性が必要でない場合、 ドラッグパラメーターの使用は意味がないわけではありません。

Source: https://habr.com/ru/post/J318254/


All Articles