Version: 2022.3
言語: 日本語
リジッドボディ物理演算
リジッドボディコライダーの設定

リジッドボディの物理演算の概要

現実世界の物理では、剛体 (rigid body、リジッドボディ) とは、物理的な力が加わっても変形しない物体を指します。同じ剛体上の任意の 2 点間の距離は、外力がかかっても、ずっと一定のまま変わりません。

移動、重力、衝突、ジョイントなどの物理ベースの動作をシミュレートするには、シーン内の要素を剛体 (リジッドボディ) として設定する必要があります。Unity の PhysX システムでゲームオブジェクトをリジッドボディとして設定するには、そのゲームオブジェクトに Rigidbody コンポーネントを割り当てます。Rigidbody コンポーネントは、API では Rigidbody クラスで表されます。

物理ベースで動くリジッドボディゲームオブジェクト

Unity の Rigidbody コンポーネントは、ゲームオブジェクトの動きと位置を物理ベースで制御する方法を提供します。Transform プロパティを使用する代わりに、シミュレートされた物理的な力とトルクを使ってゲームオブジェクトを動かし、物理演算エンジンに結果を計算させることができます。

ほとんどの場合においては、リジッドボディを持つゲームオブジェクトは、Transform プロパティではなく Rigidbody プロパティを使用して動かすことが推奨されます。Rigidbody プロパティは物理演算システムから力とトルクを適用し、それよってゲームオブジェクトの Transform が変更されます。それに加えて Transform を直接変更すると、Unity は物理シミュレーションを正しく計算できず、望ましくない動作が発生する可能性があります。これは ジョイント を持つリジッドボディでは特に顕著です。

Unity は、物理ベースの動きをローカルではなくグローバルに処理します。リジッドボディを持つゲームオブジェクトが物理ベースで動く場合、その動きは親ゲームオブジェクトや子ゲームオブジェクトからは独立したものになります。リジッドボディを持つ子ゲームオブジェクトは、初期化の際に親ゲームオブジェクトを使ってローカル位置を定義しますが、Unity は物理ベースの動きをグローバル空間で計算します。

リジッドボディをスクリプトで制御する場合、使用する主なクラスは AddForce(ゲームオブジェクトに力を加える) と AddTorque(ゲームオブジェクトにトルクを加える) です。

物理ベースで動かないリジッドボディゲームオブジェクト

場合によっては、“物理演算システムによって検出されるが制御はされない” ゲームオブジェクトが必要になることもあります。例えば “コライダー によって検出されるが、動きや位置は Transform で制御される” ゲームオブジェクトが必要な場合などです。

Unity では、物理ベースではない動きを キネマティックモーション (運動学ベースの動き/キネマティックな動き) と呼びます。Rigidbody コンポーネントには Is Kinematic というプロパティがあります。これを有効にすると、添付されたゲームオブジェクトは、“物理ベースではない” と定義され、物理演算エンジンの制御から外されます。これにより、そのゲームオブジェクトを、Transform を使用してキネマティック方式で (Unity の物理シミュレーションの計算に変更をオーバーライドされない形で) 動かせるようになります。

キネマティックなリジッドボディは、物理ベースのリジッドボディゲームオブジェクトに物理ベースの力を加えることができますが、物理ベースの力を受けることはできません。例えば、キネマティックなリジッドボディが物理ベースで動くリジッドボディに衝突してそれを “押す” ことはできますが、物理ベースで動くリジッドボディがキネマティックなリジッドボディを “押す” ことはできません。

ジョイント を使ってキネマティックなリジッドボディをキネマティックでないリジッドボディにアタッチした場合、そのジョイントは、キネマティックなリジッドボディを動かす力を加えることはできません。このジョイントはキネマティックでないリジッドボディしか動かせません。ただし、Transform を使用すれば、キネマティックなリジッドボディを動かすことが可能で、ジョイントは、キネマティックでないリジッドボディのポーズを、ジョイントの制限に合わせて調整することができます。

リジッドボディの最適化

Sleep Threshold (Project Settings の Physics 設定 参照) より遅い速度で動くリジッドボディは、Unity によって “スリープ” 状態に設定されます (つまり、そのリジッドボディは物理演算システムの物理演算に含まれなくなります)。スリープ状態のリジッドボディは、衝突や力を受けると Unity によって “起こされ”、物理演算に含まれるようになります。

デフォルトでは、Rigidbody コンポーネントのスリープとスリープ解除は自動的に行われます。ただし、この動作は、Rigidbody.Sleep メソッドと Rigidbody.WakeUp メソッドを使用してスクリプトで制御することも可能です。

リジッドボディは、物理演算システムではなく Transform の位置に基づいて動いている静的コライダー (つまりリジッドボディを持たないコライダー) の動きや衝突を受けた場合に、スリープ解除に失敗することがあります。これは特に、物理演算システムが静的コライダーを検出できなくなった場合に発生しやすくなります。このような場合は、Rigidbody.WakeUp を使用して、スリープ状態のリジッドボディを起こすことができます。

PhysX 物理演算システムのスリープ処理の詳細は、NVIDIA PhysX SDK Rigidbody Dynamics ドキュメントの Sleeping セクション を参照してください。

リジッドボディ物理演算
リジッドボディコライダーの設定