脱初心者を目指すUnityブログ。
今日は Rigidbody について基礎をおさらいしつつ、便利な関数等を調べ試してみたいと思います。
Rigidbody のプロパティ
まずは Rigidbody コンポーネントのプロパティをおさらい。
Mass
オブジェクトの質量。Mass 1 = 1kg
Drag
空気抵抗。落下速度などに影響する。厳密な物理計算を必要としない場面では、0にしても問題無いケースが多い。
Angular Drag
回転に対する空気抵抗。0だと回り続け、値を大きくすると回転が止まりやすくなる。
Use Gravity
重力の影響を受けるか否か。OFF だと無重力状態のように扱える。
Is Kinematic
物理演算をするか否か。チェックを入れると物理演算では動かないオブジェクトになる。
Interpolate
物理演算の効果を滑らかにする設定。あまり使うことはない。
Collision Detection
衝突の判定方式。動きが速いオブジェクトは衝突判定がすり抜けてしまう場合があるので、この設定で対処する。
Constraints
PositionやRotationの動きに動きに制約をかける。チェックを入れた軸の回転や移動を制限。
Info
物理演算の内部挙動を確認できる。インスペクター上ではいじれないが、スクリプトからアクセスできる。
併せて知っておきたい Physic Material
物理演算と一緒に使われることの多い Physic Material のプロパティも併せて確認しておきます。
摩擦や反発の設定をし、オブジェクトの物理的な特性を設定することができます。
ツルツルの床や、ボールのようによく跳ねる球などが簡単に表現できる便利機能です。
Projectビューで右クリック > Create > Physic Material で新規作成、
設定後Collider の Material にアタッチして使用します。
Dynamic Friction
動いている物体が摩擦により静止する際の、摩擦の強さの値。基本的に0~1で設定。
0だと摩擦なく滑り、1だとすぐに動きが止まる。
Static Friction
静止している物体に力を加えた時の摩擦を表現する値。基本的に0~1で設定。
0だと摩擦なく滑って動き出し、1だとすぐに動きが止まります。
Bounciness
弾性の表現をする値。0~1で設定。
0だと全く跳ね返らない、1だとよく跳ね返る。(床も物体も1だと、跳ねる高さが増え続ける)
Friction Combine
オブジェクト同士が衝突した際の摩擦の計算方法が選べる。リファレンスのコピペ↓
Average : 2 つの摩擦力が平均化されます。
Minimum : 2 つの摩擦力のうち小さい方の値が使用されます。
Maximum : 2 つの摩擦力のうち大きい方の値が使用されます。
Multiply : 2 つの摩擦力が互いに乗算されます。
Bounciness
オブジェクト同士が衝突した際の跳ね返りの計算方法が選べる。
選べる項目は上記Friction Combineと同じ。
Rigidbody の便利な変数
ここからはリファレンスをもとに、よく使うらしい変数を実際に使ってまとめていきます。
Rigidbody.mass
Rigidbody.drag
Rigidbody.angularDrag
Rigidbody.useGravity
Rigidbody.isKinematic
Rigidbody.consrtaints
上記の「Rigidbody のプロパティ」を参照する変数です。スクリプトから値を変更できます。
簡単なので、 constraints だけ例を挙げます。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); // 2回書いてしまうと、新しい方しか反映されない。 // よって、下記「PositionZを固定」は反映されない。 rb.constraints = RigidbodyConstraints.FreezePositionZ; //すべての軸で、回転しなくなる。 | で切って並べれば、複数のConstraintsを制御できる。 rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationY | RigidbodyConstraints.FreezeRotationZ; }
Rigidbody.velocity
速度ベクトル。動く速度を直接変更したい場合に使います。
FPSゲームのジャンプなどで使われている印象。(ポーンと跳ねるような、軽い感じの動き)
velocity の値は、本来ならば物理演算の結果として変化します。それを直接変更することになるので非現実的な動きになりやすく、注意が必要。自然な動きを作るならば、後述 AddForce の方が良いです。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void Update() { if(Input.GetKeyDown("space")) { //上へ跳ねる。重量感の無い軽い動き。 rb.velocity = new Vector3(0, 5, 0); } }
Rigidbody.angularVelocity
角速度ベクトル。回転する速度を直接変更したい場合に使います。
例えば 物体の動きをピタッと止めたい場合、 velocity と angularVelocity を0にしてしまえば良いということになります。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); rb.AddForce(new Vector3(0, 0, 5), ForceMode.Impulse); } void Update() { if (Input.GetKeyDown("space")) { //ピタッと止める rb.useGravity = false; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } }
Rigidbody の便利な関数
続けて、よく使うらしい関数を実際に使いながらまとめていきます。
Rigidbody.AddForce(Vector3, ForceMode);
Rigidbody に力を与えます。
引数は 力の大きさベクトル と ForceMode(力の与え方を4種類から選ぶ) の2つです。
継続的に力を与える場合、UpdateではなくFixedUpdate内で使った方が正確な実装ができます。
ForceMode の種類
●継続的な動き
・Force
質量を使用して、Rigidbody に継続的な力を加える。車が走り続ける動きなど。
・Acceleration
質量を無視して、Rigidbody に継続的な力を加える。質量関係なく一定の力を加えたいときに。
●瞬発的な動き
・Impulse
質量を使用して、Rigidbody に瞬間的に力を加える。サッカーボールを蹴る瞬間など。
・VelocityChange
質量を無視して、Rigidbody に瞬間的に力を加える。FPSゲームのジャンプなどのイメージ。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void FixedUpdate() { rb.AddForce(new Vector3(0, 0, 5) , ForceMode.Force); }
Rigidbody.AddTorque(Vector3, ForceMode);
Rigidbody に回転を与えます。
引数は 回転の力の大きさベクトル と ForceMode(上述と同じ) の2つです。
実際の回転の仕方は、ねじ回しをイメージするとわかり易いです。そのベクトルの方向軸を基準に、+なら時計回り -なら反時計回りに回転します。
継続的に力を与える場合、UpdateではなくFixedUpdate内で使った方が正確な実装ができます。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); rb.AddTorque(new Vector3(0, 0, 5), ForceMode.Impulse); }
Rigidbody.IsSleeping();
Rigidbody が静止状態(後述 Sleepモード)か否かを取得できます。
void Update() { // true か false が返る Debug.Log(rb.IsSleeping()); }
Rigidbody.WakeUp();
ほぼ動いていない状態になった時、Rigidbody はSleepモードになります。
SleepモードになったRigidbody は、基本的には再び力が与えられるまで物理計算が止まったままです。
(最近のUnityだと、直下の床が消えた時はRigidbodyが目覚める模様。)
例えば、Sleepモードのスフィアの下の床が傾いても、物理計算がSleepしているので転がりません。
WakeUp を使って強制的に Rigidbody を「起こす」必要があります。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void Update() { Debug.Log(rb.IsSleeping()); if (Input.GetKeyDown("space")) { rb.WakeUp(); } }
Rigidbody.Sleep();
上記のSleepモードを強制的に適用します。
UseGravity が true の場合は true のまま、Sleepモードになっている間はその場で静止し続けます。
private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void Update() { if (Input.GetKeyDown("space")) { if(rb.IsSleeping()) { rb.WakeUp(); } else { rb.Sleep(); } } }
おわりに
Rigidbody の主要な機能は大体触れられたかなと思います。
自分で手を動かしてみると、新しい発見がありますね!今回はここまで。