この記事はUnityのコンポーネントRigidbodyについて解説している記事です。
RigidbodyはUnityの物理演算について関わりが深いので、物理演算がよくわからないよという方は↓の記事を参考にしてください。
- <Rigidbodyとは>
- <Transform操作と物理エンジン操作>
- <Rigidbodyを使用する際の注意点>
- <Rigidbodyのインスペクター>
- <Rigidbodyのスクリプトの使い方>
- angularDrag
- angularVelocity
- centerOfMass
- collisionDetectionMode
- constraints
- detectCollisions
- drag
- freezeRotation
- inertiaTensor
- inertiaTensorRotation
- interpolation
- isKinematic
- mass
- maxAngularVelocity
- maxDepenetrationVelocity
- position
- rotation
- sleepThreshold
- solverIterations
- solverVelocityIterations
- useGravity
- velocity
- worldCenterOfMass
- AddExplosionForce
- AddForce
- AddForceAtPosition
- AddRelativeForce
- AddRelativeTorque
- AddTorque
- ClosestPointOnBounds
- GetPointVelocity
- GetRelativePointVelocity
- IsSleeping
- MovePosition
- MoveRotation
- ResetCenterOfMass
- ResetInertiaTensor
- SetDensity
- Sleep
- SweepTest
- SweepTestAll
- WakeUp
- <Force Modeの使い方>
- <Force Modeのスクリプト>
<Rigidbodyとは>
アタッチしたゲームオブジェクトが物理演算で挙動するようになるコンポーネントです。
コライダーがついている子オブジェクトも挙動の影響を受けます。
ゲームオブジェクト単体にRigidbodyをつけると↓のようになります。
Rigidbodyをつけたゲームオブジェクトに子オブジェクトが有る(SphereはCubeの子)と↓のようになります。
このように子オブジェクトがあると子オブジェクトを全て合わせて計算されます。
なお、コライダーがセットされていない子オブジェクトは考慮されないので注意してください。
↓Sphereのコライダーをオフにしている状態
<Transform操作と物理エンジン操作>
Unityで物体を動かそうと思った時、次の2パターンにの動き方になります。
・Transform操作・・・位置情報を直接制御する方法(ただ移動するだけ)
・物理エンジン操作・・・物理演算でオブジェクトの位置を制御する方法(オブジェクトを動かした時周囲の状況により様々な計算が入る)
Rigidbodyをゲームオブジェクトにアタッチした場合、デフォルトでTransform操作でしか動かせなかったオブジェクトが、物理演算を用いた操作方法が可能になります。
子オブジェクトも影響を受けます。
物理演算で動いているオブジェクトをTransform操作することは可能ですが、Rigidbodyがついていないオブジェクトを物理演算挙動で動かすことはできません。(自作やフレームワークを使わない限り)
Rigidbodyをアタッチすると動き方の根本が変わってしまう事に注意してください。
<Rigidbodyを使用する際の注意点>
Rigidbodyを使用するにあたって気をつけるべき事があります。それは
物理演算挙動で動作しているものがある状態で、物理演算に関連性があるオブジェクトのTransformの値を変えると再計算が行われる。
という点です。これめちゃくちゃ重要なので覚えておいてください。
物理演算というのは非常に重い処理です。慎重に取り扱わないとゲームがカクカクになります。再計算が行われるということはさらに重くなるということです。
どういうことかというと↓の図は
・左がRigidbody有り
・右がRigidbody無し
で、両方にBoxColliderがついています。BoxColliderは物理演算に関連性のあるコンポーネントです。
この状態で無しのオブジェクトを動かすと、有りのオブジェクトに再計算が走ります。
有りのオブジェクトが動かなくても、二つが衝突しなくても再計算が走ります。
これはそもそもオブジェクトの移動が瞬間移動であるので、再計算せざるをえないのです。
オブジェクトの移動については↓の記事にまとめましたので、よくわからない方は参考にしてください。
オブジェクトの移動は瞬間移動なのですが、Transformの瞬間移動と物理演算での瞬間移動は違います。
Transformは瞬間移動させるだけなのですが、物理演算は瞬間移動させる際にあれこれ計算してから瞬間移動させています。ある地点に物体を移動させようとした時、そこに何があるのか、どういった影響を受けるのか事前に計算して最終的に瞬間移動する位置を決めて移動させているわけです。
そこに突然物理演算外から瞬間移動してくる物体があった場合、例えRigidbodyがついたオブジェクトが動いていなくても、外から瞬間移動してきた物体とぶつかっているかどうかわからないので再計算が走るわけです。
問題になる例をあげると、アクションゲームでキャラクターをRigidbodyで動かしたとます。そして、動く床をTransformで動かしたとします。
この動く床を大量に配置した場合ゲームがカクカクになりやすいです。
この「なりやすい」というのがミソでTransformで動いているものが1個で処理が少し重くなります。多少であれば大丈夫です。
でも少しは重くなっているので、ゲーム中に配置すればするほどジワリジワリと重くなっていき、30FPSを切った瞬間カクカクになります。
これのマズイところは初心者には原因の特定がしづらい点です。何故なら今までは普通に動いていたのですから。また、スマホやブラウザに移した瞬間カクカクになったりします。
対策としては「物理エンジンに関係するオブジェクトは物理演算による移動を行うようにする」です。
Transformの移動ではなくRigidbodyを通した移動を行うとよいでしょう。
ちなみにアニメーションによる移動はTransformの移動です。
Rigidbodyを通した移動はスクリプトから行う必要があります。スクリプトについては↓↓の方で解説しています。
<Rigidbodyのインスペクター>
・Mass・・・物体の質量を決めます(Kg単位)
・Drag・・・空気抵抗。0で抵抗無し。無限で動かなくなる
・Angular Drag・・・回転する際の空気抵抗。0で抵抗無し。無限にしても回転はする
・Use Gravity・・・オンで重力の影響を受けるようになる。落下速度はMassを調整しよう
・IsKinematic・・・オンで物理演算の影響を受けなくなる
・Interpolate・・・移動の際の補間方法を選ぶ
・CollisionDetection・・・コライダーの計算方法を選ぶ
・Constraits・・・オブジェクトの動きに制限を設ける
IsKinematicについて
Rigidbodyがついているオブジェクトが物理演算の影響を受けなくなります。
これって意味あるの?って話なのですが、もちろんあります。
例えばRigidbody概要の方で説明した処理が重くなる話ですが、物理的な動きをしない物を動かしたい時(例えば動く床等)RigidbodyをつけてIsKinematicをオンにすればTransform的な移動ではなく物理演算的な移動にする事ができます。
また、物理演算で動いていたものを途中でTransform的な動きに切り替えたい時にオンにする使い方もできます。(特定のアクションの間は物理演算ではない挙動にしたい等)
Interpolateについて
移動の際の補間方法を選びます。
物理演算を行う計算タイミングと画面に物体を描画するタイミングが違うので、オブジェクトの移動がガクガクします。
このタイミングによるズレを考えて計算するよという事です。物理演算のタイミングはFixedUpdateで描画タイミングはUpdateです。
・None・・・補間を行わない
・Interpolate・・・直前フレームの速度を使って補間
・Extrapolate・・・現在の速度から次フレームの位置を予測して補間
補間をオンにすると当然重くなります。Interpolateの方が重いです。Extrapolateの方が軽いですが予測補間なので変な位置に描画されるリスクがあります。
使いどきは移動がガクガクする奴がいる時でしょうか。基本はNoneで大丈夫です。
CollisionDetectionについて
Unityの移動は瞬間移動である為、当たり判定のすり抜け等が起こります。これを防ぐ為に計算方法を選びます。
瞬間移動する前とした後の間にコライダーがあるとすり抜けてしまいます。
・Discrete
デフォルト設定です。瞬間移動した時に衝突しているかどうかをみます。
・Continuous
「Rigidbodyなしのコライダー」と「RigidbodyのContinuous Dynamicの設定がされているコライダー」に対して事前に計算を行なってから衝突しているかどうかをみます。その他のコライダーに対しては瞬間移動した時に衝突しているかどうかをみます。
・Continuous Dynamic
「RigidbodyのDiscreteが設定されているコライダー」のみ瞬間移動した時に衝突しているかどうかをみます。その他のコライダーは事前に計算を行なってから衝突しているかどうかをみます。
この時、瞬間移動した時に衝突しているかどうかをみる事を離散型衝突検知といい、事前に計算を行なって衝突しているかどうかをみる事を連続型衝突検知といいます。連続型衝突検知はものすごく複雑な計算を行なっているので、これにすると重くなります。
基本はDiscreteにしておき、当たり判定のすり抜け等がおきたら他2つの設定を検討してみると良いでしょう。
Constraitsについて
オブジェクトの動きに制限を設けます。
Freeze Position・・・位置情報を固定します。x,y,zのチェックした値が固定されます。つまりチェックした項目が動かなくなります。
Freeze Rotation・・・回転情報を固定します。x,y,zのチェックした値が固定されます。つまりチェックした項目が回転しなくなります。
<Rigidbodyのスクリプトの使い方>
名前空間 | UnityEngine |
型 | class |
継承 | Component |
angularDrag
回転する際の抵抗です。
0で抵抗無し。無限にしても回転はします。
型 float型
○ 使い方
回転のしやすや、し辛さを設定したい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.angularDrag = 1.1f;
angularVelocity
角速度です。
型 Vector3型
○ 使い方
角速度を設定したい場合に使用します。この値は、様々な物理計算の後に入るので、基本的には読み取り用として使います。この値を直接触った場合、物理法則を無視した動きになりやすいです。
Rigidbody rb = GetComponent<Rigidbody>();
rb.angularVelocity = new Vector3(1.1f,1.1f,1.1f);
centerOfMass
重心です。
Transformの原点からの位置を指定します。指定しなかった場合、コライダー全体から自動計算されます。スケールは反映されていないので計算する必要があります。
型 Vector3型
○ 使い方
重心を変更したい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.centerOfMass = Vector3.Scale(new Vector3(1.1f,2.2f,3.3f),gameObject.transform.localScale );
Vector3.Scaleは2つのVector3の各要素を乗算するもの
collisionDetectionMode
コライダーの計算方法です。詳しくはインスペクターの項目に記載してあります。
型 CollisionDetectionMode型
・Discrete このモードは連続検出モードをオフにします。
・Continuous このモードは静的メッシュジオメトリと衝突しているときに検出されるようになります。
・ContinuousDynamic このモードは静的と動的ジオメトリと衝突しているときに検出されるようになります。
・ContinuousSpeculative 静的および動的ジオメトリに対して投機的連続衝突検出がオンになっています
○ 使い方
コライダーのすり抜けが特定の場面だけの場合、そこだけ変更して、元に戻す事で処理負荷を軽減できるなどの使い方ができます。
Rigidbody rb = GetComponent<Rigidbody>();
rb.collisionDetectionMode = CollisionDetectionMode.Discrete;
constraints
オブジェクトの動きに制限を設けます。詳しくはインスペクターの項目に記載してあります。
型 RigidbodyConstraints型
enum型です。
None 制限なし
FreezePositionX X 軸の移動をさせない
FreezePositionY Y 軸の移動をさせない
FreezePositionZ Z 軸の移動をさせない
FreezeRotationX X 軸の回転をさせない
FreezeRotationY Y 軸の回転をさせない
FreezeRotationZ Z 軸の回転をさせない
FreezePosition 移動させない
FreezeRotation 回転させない
FreezeAll 移動と回転をさせない
○ 使い方
オブジェクトの動きに制限を設けたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.constraints = RigidbodyConstraints.FreezePositionX | RigidbodyConstraints.FreezeRotationZ;
enum型なので値はビット演算で指定できます
detectCollisions
コリジョンの衝突検出するかどうかです。
デフォルトではtrueになっています。
型 bool型
○ 使い方
コリジョンの衝突のオンオフをしたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.detectCollisions = false;
drag
移動する際の抵抗です。
0で抵抗無し。無限で動かなくなります。
型 float型
○ 使い方
オブジェクトの動かしやすさ、動かしにくさを設定する際に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.drag = 1.1f;
freezeRotation
物理演算による回転の影響を受け無いようにするかどうかです。
デフォルトでfalseになっています。
型 bool型
○ 使い方
回転させないようにしたい時に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.freezeRotation = true;
inertiaTensor
主慣性モーメントです。
3次元の主慣性モーメントが3X3の対角行列なので、データの節約でmatrixではなくVector3で表しています。intertiaTensorRotationとセットで慣性モーメントテンソルになります。また各種値は固有値なので、大きくすると回転しづらくなります。
<注意>
この値をいじる前に力をかけてしまうと、そのかかった力はinertiaTensorの影響を受けません。
また、値を0以下にする事は出来ません。
型 Vector3型
○ 使い方
回転のしやすさ、しにくさを変更したい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.inertiaTensor = new Vector3(1.1f,1.1f,1.1f);
inertiaTensorRotation
慣性モーメントテンソルの固有ベクトルです。
行列ではなくQuaternionで返ってきます。これは3次元回転行列なので(主慣性モーメント参照)Quaternionに変換することができるため、データ節約によりmatrixではなくQuaternionで表しています。慣性テンソルの回転行列であるため回転軸の角度を変えることができます。デフォルトの回転軸はローカル軸と同じです。
<注意>
回転軸を変えることができると言っても、回転軸を直接変えているわけではなく、角速度ωと角運動量Lとの角度を変えているだけです。そのため回転軸を変えようというイメージでいじると違う結果になりがちです。また立方体のような左右上下対称な物のinertiaTensorRotationを変えても変化はほとんど見られないです。また、この値をいじる前に力をかけてしまうと、そのかかった力はinertiaTensorRotationの影響を受けません。
型 Quaternion型
○ 使い方
主に回転軸を角度を変えるのに使用します。直感的な軸では無いので注意してください。
Rigidbody rb = GetComponent<Rigidbody>();
rb.inertiaTensorRotation = Quaternion.Euler(new Vector3(1.1f,1.1f,1.1f));
interpolation
移動の際の補間方法です。
詳しくはインスペクターの項目に記載してあります。
型 RigidbodyInterpolation型
enum型です。
None 補間しません
Interpolate 補間を行います Extrapolate より少し反応が遅れる場合があります
Extrapolate 外挿補間を行います 現在の速度に基づいて計算されます
○ 使い方
移動の際の補間方法を変更したい時に使用します。ある特定の場面で高速で移動したい場合、そこだけ変更して、元に戻す事で処理負荷を軽減できるなどの使い方ができます。
Rigidbody rb = GetComponent<Rigidbody>();
rb.interpolation = RigidbodyInterpolation.Extrapolate;
isKinematic
物理演算の影響を受けるかどうかです。
詳しくはインスペクターの項目に記載してあります。
型 bool型
○ 使い方
物理演算による影響をオンオフで切り替えたい時に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.isKinematic = true;
mass
質量です。
単位はkgです。
型 float型
○ 使い方
物体の質量を設定したい時に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.mass = 1.1f;
maxAngularVelocity
最大角速度です。
この物体の角速度はこの値以上にはなりません。デフォルトは7です。360度は2πなので、2π=6.28・・・になります。デフォルトの状態は1秒間に1回転ちょっと回るのが限界ということになります。これは、あまり速くしすぎると挙動に破綻が起きるからです。
型 float型
○ 使い方
回転に制限をかけたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.maxAngularVelocity = 1.1f;
maxDepenetrationVelocity
コリジョンが衝突している時、そこから離れようという挙動の最大速度です。
型 float型
○ 使い方
主に衝突後の調整をするために使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.maxDepenetrationVelocity = 1.1f;
position
ゲームオブジェクトの位置を動かします。
物理シミュレーションの後に位置の移動が行われます。transform.positionは物理演算の再計算が発生するので、物理演算で動いているオブジェクトはこちらを使用した方が軽いです。MovePosition()との違いは補間の計算が入らない点です。
型 Vector3型
○ 使い方
物理演算を使用している物体の位置を動かす場合はtransform.positionではなく、こちらを使用しましょう。
Rigidbody rb = GetComponent<Rigidbody>();
rb.position = new Vector3(1.1f,1.1f,1.1f);
rotation
ゲームオブジェクトの回転させます。
物理シミュレーションの後に回転が行われます、transform.rotationは物理演算の再計算が発生するので、物理演算で動いているオブジェクトはこちらを使用した方が軽いです。MoveRotation()との違いは補間の計算が入らない点です。
型 Quaternion型
○ 使い方
物理演算を使用している物体の姿勢を変える場合はtransform.rotationではなく、こちらを使用しましょう。
Rigidbody rb = GetComponent<Rigidbody>();
rb.rotation = Quaternion.Euler(new Vector3(1.1f,1.1f,1.1f));
sleepThreshold
このオブジェクトの「正規化された質量の運動エネルギー」がこの値以下になった時、このオブジェクトは動いていないとみなされます。
実際の動きも止まります。デフォルトの値はUnityの上部メニューのEdit > ProjectSetting > Sleep Thresholdの値です。動いていないとみなされると計算がスキップされ、処理が軽くなります。
型 float型
○ 使い方
このしきい値を大きくしておけば、それだけオブジェクトが動いている時間が少なくなるので、処理を軽くしたい時に使えます。
Rigidbody rb = GetComponent<Rigidbody>();
rb.sleepThreshold = 1.1f;
solverIterations
他のRigidbodyとの衝突やジョイントの際に行われる物理演算のソルバー反復回数を変更します。
デフォルトの値はEdit > ProjectSetting > Default Solver Iterationsの値です。大きくすると精度が上がりますが、処理負荷も増えます。回数なのでint型です。
型 int型
○ 使い方
正確な物理演算の結果を得たい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.solverIterations = 1;
solverVelocityIterations
他のRigidbodyとの衝突やジョイントの際に行われる速度計算でのソルバー反復回数を変更します。
デフォルトの値はEdit > ProjectSetting > Default Solver Velocity Iterationsの値です。大きくすると精度が上がりますが、処理負荷も増えます。回数なのでint型です。
型 int型
○ 使い方
正確な物理演算の結果を得たい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.solverVelocityIterations = 1;
useGravity
重力の影響を受けるかどうかを設定します。
重力の値はEdit > ProjectSetting > Gravityの値です。
型 bool型
○ 使い方
重力の有無の切り替えなどに使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.useGravity = true;
velocity
速度ベクトルです。
物理シミュレーションを無視して値を入れることになるので、挙動が非現実的になります。
型 Vector3型
○ 使い方
オブジェクトに速さをつけたい場合に使用します。ただし、物理演算の計算を無視する点に気をつけてください。
Rigidbody rb = GetComponent<Rigidbody>();
rb.velocity = new Vector3(1.1f,1.1f,1.1f);
worldCenterOfMass
ワールド座標における質量の中心位置です。
読み取り専用です。
型 Vector3型
○ 使い方
質量の中心位置を取得して、様々な計算に使用するのに使います。
Rigidbody rb = GetComponent<Rigidbody>();
Vector3 this_world_mass = rb.worldCenterOfMass;
AddExplosionForce
この物体に対して爆発をシミュレーションした力を加えます。
1. 爆発の中心位置での力 : float型
2. 爆発した場所のワールド座標 : Vector3型
3. 爆発の影響がある場所の半径 : float型
4.爆発の力の働きかけをY軸上で調整する値 : float型 (デフォルト引数 0.0f)
5. 力の掛け方 : ForceMode型 (デフォルト引数 ForceMode.Force)
4は爆発の中心位置と半径を変えずに、見かけ上の力が働く位置を調整するものです。爆発での吹っ飛びでより高く飛ばしたい等の時に使用します。
なし
○ 使い方
この関数はこのオブジェクトに対してのみ行われるので、爆発の演出をする際は吹っ飛ぶオブジェクト全部のRigidbodyのこの関数を呼ぶ必要があります。
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddExplosionForce(1.1f,new Vector3(1.1f,1.1f,1.1f),1.1f,1.1f,ForceMode.Acceleration);
AddForce
この物体に対して力を加えます。
1. この物体に与える力のベクトル : Vector3型
2. 力のタイプ : ForceMode型 (デフォルト引数 ForceMode.Force)
1のベクトルはワールド座標下で計算されたものです。
なし
○ 使い方
Rigidbodyを扱う上で最も基本的な関数です。物体を動かすのによく使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(new Vector3(1.1f,1.1f,1.1f), ForceMode.Acceleration);
AddForceAtPosition
特定の位置からこの物体に対して力を加えます。
1. この物体に与える力のベクトル : Vector3型
2. 力の発生源の場所 : Vector3型
3. 力のタイプ : ForceMode型 (デフォルト引数 ForceMode.Force)
1のベクトル、および2の場所はワールド座標下で計算されたものです。
なし
○ 使い方
何らかの離れた位置からの力を加えるのに便利です。
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForceAtPosition(new Vector3(1.1f,1.1f,1.1f), new Vector3(1.1f,1.1f,1.1f), ForceMode.Acceleration);
AddRelativeForce
この物体に対して力を加えます。
1. この物体に与える力のベクトル : Vector3型
2. 力のタイプ : ForceMode型 (デフォルト引数 ForceMode.Force)
1のベクトルはローカル座標下で計算されたものです。
なし
○ 使い方
物体を動かすのに使用します。ローカル座標基準な点に注意してください。
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(new Vector3(1.1f,1.1f,1.1f), ForceMode.Acceleration);
AddRelativeTorque
この物体に対してトルクを加えます。
1. この物体に与えるトルクのベクトル : Vector3型
2. 力のタイプ : ForceMode型 (デフォルト引数 ForceMode.Force)
1のベクトルはローカル座標下で計算されたものです。
なし
○ 使い方
物体を回転させるのに使用します。ローカル座標基準な点に注意してください。
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddRelativeTorque(new Vector3(1.1f,1.1f,1.1f), ForceMode.Acceleration);
AddTorque
この物体に対してトルクを加えます。
1. この物体に与えるトルクのベクトル : Vector3型
2. 力のタイプ : ForceMode型 (デフォルト引数 ForceMode.Force)
1のベクトルはワールド座標下で計算されたものです。
なし
○ 使い方
物体を回転させるのに使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddTorque(new Vector3(1.1f,1.1f,1.1f), ForceMode.Acceleration);
ClosestPointOnBounds
このオブジェクトにアタッチされたコライダーのバウンディングボックスの面上で、指定したある点と最も近い場所を返します。
1. どこでもいいので特定の位置(ワールド座標) : Vector3型
バウンディングボックスの面上で、指定したある点と最も近い場所 : Vector3型
○ 使い方
例えば、コライダーにヒットした場所にダメージ表示をする時など、色々な使い道があります。
ダメージ表示の際にこれを使用するのはコライダーがヒットした場所をそのままダメージ表示する場所に指定してしまうとモデルに文字がめり込むからです。
Rigidbody rb = GetComponent<Rigidbody>();
Vector3 v = rb.ClosestPointOnBounds(new Vector3(1.1f,1.1f,1.1f));
GetPointVelocity
ワールド座標における、Rigidbodyの速度ベクトルを取得します。
とは言っても、ある座標での速度を測るような予測機能のようなものではなく、そのオブジェクトが回転することを考えて、ある座標での瞬間速度はどれくらい出ているかを表したものです。
↓は横に長い箱の全体の速度と箱から右側3mの位置を測定しています。
(velocityとGetPointVelocity(transform.position + Vector3.right * 3)を比較しています。)
↓箱同士がぶつかるまでは同じ速度で動いていることがわかります。
↓これはこういうことです
ところが箱がぶつかった後、こうなります。
右端の速度がyの成分だけ↓方向に速くなっています。
回転しているのに何故斜めではなく↓方向だけ速くなっているかというと
これはグローバル座標を取っているので回転している箱の右端を取っているわけではなく
箱の位置からグローバル座標で右側なので
transform.position + Vector3.right * 3は空間的に↓の青矢印になります。
この時、青の矢印が始まる始点では角速度ω分プラスされることになるので↓方向のみ速度が速く計算されたという形になります。
1. どこでもいいので特定の位置(ワールド座標) : Vector3型
Rigidbodyの速度ベクトル : Vector3型
○ 使い方
このオブジェクトの特定の位置の速度ベクトルが知りたい場合に使用します。
使い方
Rigidbody rb = GetComponent<Rigidbody>();
Vector3 v = rb.GetPointVelocity(new Vector3(1.1f,1.1f,1.1f));
GetRelativePointVelocity
↑のGetPointVelocityの反対でローカル座標での速度ベクトルを取得します。
GetPointVelocityとは違い、返ってくる値は青と赤のベクトルの合計になります。
1. どこでもいいので特定の位置(ローカル座標) : Vector3型
Rigidbodyの速度ベクトル : Vector3型
○ 使い方
このオブジェクトの特定の位置の速度ベクトルが知りたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
Vector3 v = rb.GetRelativePointVelocity(new Vector3(1.1f,1.1f,1.1f));
IsSleeping
このオブジェクトが動いているかどうかです。
このオブジェクトの「正規化された質量の運動エネルギー」がsleepThresholdの値以下になった時、このオブジェクトは動いていないとみなされます。デフォルトの値はUnityの上部メニューのEdit > ProjectSetting > Sleep Thresholdの値です。
なし
スリープ状態かどうか : bool型
○ 使い方
このオブジェクトが動いているのか知りたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>(); if(rb.IsSleeping()) { Debug.Log("動いていないよ"); }
MovePosition
ゲームオブジェクトの位置を動かします。
transform.positionは物理演算の再計算が発生するので、物理演算で動いているオブジェクトはこちらを使用した方が軽いです。Rigidbody.positionとの違いは補間の計算が入る点です。
1. どこでもいいので特定の位置(ワールド座標) : Vector3型
なし
○ 使い方
移動に対し補間が入るため、オブジェクトをFixedUpdate内で動かすのにちょうどいい関数です。
Rigidbody rb = GetComponent<Rigidbody>();
rb.MovePosition(new Vector3(1.1f,1.1f,1.1f));
MoveRotation
ゲームオブジェクトの回転させます。
transform.rotationは物理演算の再計算が発生するので、物理演算で動いているオブジェクトはこちらを使用した方が軽いです。Rigidbody.rotationとの違いは補間の計算が入る点です。
1. 回したい回転情報 : Quaternion型
なし
○ 使い方
移動に対し補間が入るため、オブジェクトをFixedUpdate内で動かすのにちょうどいい関数です。
Rigidbody rb = GetComponent<Rigidbody>();
rb.MoveRotation(Quaternion.Euler(new Vector3(1.1f,1.1f,1.1f)));
ResetCenterOfMass
重心をデフォルトの設定に戻します。
このデフォルトはUnity側がオブジェクトの形や大きさから自動計算した値です。オブジェクトに何らかの変更が加えられた後これを呼び出すと、再度自動計算された値になります。
なし
なし
○ 使い方
重心を元に戻したい時に使用します。
使い方
Rigidbody rb = GetComponent<Rigidbody>();
rb.ResetCenterOfMass();
ResetInertiaTensor
主慣性モーメントと慣性モーメントテンソルの回転をデフォルトの状態に戻します。
このデフォルトはUnity側がオブジェクトの形や大きさから自動計算した値です。オブジェクトに何らかの変更が加えられた後これを呼び出すと、再度自動計算された値になります。
なし
なし
○ 使い方
オブジェクトの慣性モーメントをリセットしたい時に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.ResetInertiaTensor();
SetDensity
密度を設定します。
密度が変わるのでコライダーのサイズからmass(質量)の値を自動計算して変更してくれます。何故かインスペクターのmassの値は変わりませんが、実際の値は変わっています。
1.密度 : float型
なし
○ 使い方
物体の密度を変えたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.SetDensity(1.1f);
Sleep
1フレームの間、強制的にRigidbodyを動かさないようにします。
ずっとスリープにするのではなく、1フレームのみなので注意が必要です。ずっとスリープにするのならIsKinematicをtrueにしましょう。
なし
なし
○ 使い方
物体の動きを1フレームだけ止めたい場合に使用します。
Rigidbody rb = GetComponent<Rigidbody>();
rb.Sleep();
SweepTest
衝突の予測計算ができます。
1. 予測する方向 : Vector3型
2. 衝突した際の情報を格納するもの : RaycastHit型 (参照渡し)
3. 予測の最大距離 : float型 (デフォルト引数 Mathf.Infinity)
4. トリガー設定(IsTriggerがオンになっているもの)を対象にする設定の種類 : QueryTriggerInteraction型 (デフォルト引数 QueryTriggerInteraction.UseGlobal)
QueryTriggerInteractionはenum型です。
UseGlobal クエリは、グローバル Physics.queriesHitTriggers 設定を使用します
Ignore クエリはトリガーの発生を報告しません
Collide クエリは、常にトリガーの発生を報告します
何かと衝突したかどうか : bool型
この関数がtrueを返してきた時、引数として渡したRaycastHitに衝突した際の情報が格納されます。
○ 使い方
衝突の予測がしたい場合に便利です。
RaycastHit h = new RaycastHit(); Rigidbody rb = GetComponent<Rigidbody>(); if(rb.SweepTest(new Vector3(1.1f,1.1f,1.1f), out h, 1.1f, QueryTriggerInteraction.Ignore)) { Debug.Log(h.collider.name + "にぶつかると予測できます"); }
SweepTestAll
衝突の予測計算で衝突されると予測された全ての情報を取得します。
1. 予測する方向 : Vector3型
2. 予測の最大距離 : float型 (デフォルト引数 Mathf.Infinity)
3. トリガー設定(IsTriggerがオンになっているもの)を対象にする設定の種類 : QueryTriggerInteraction型 (デフォルト引数 QueryTriggerInteraction.UseGlobal)
QueryTriggerInteractionはenum型です。
UseGlobal クエリは、グローバル Physics.queriesHitTriggers 設定を使用します
Ignore クエリはトリガーの発生を報告しません
Collide クエリは、常にトリガーの発生を報告します
衝突されると予想された全ての情報 : RaycastHit[]型
○ 使い方
衝突されると予測される全ての情報を取得したい場合に便利です。
Rigidbody rb = GetComponent<Rigidbody>();
RaycastHit[] h = rb.SweepTestAll(new Vector3(1.1f,1.1f,1.1f), 1.1f, QueryTriggerInteraction.Ignore);
WakeUp
強制的にスリープモードを解除します。ずっと続くわけではなく、呼び出した1フレームのみ有効です。
なし
なし
○ 使い方
強制的にスリープモードを解除したい場合に使用します。1フレームのみ有効ですのでご注意を
Rigidbody rb = GetComponent<Rigidbody>();
rb.WakeUp();
変数や関数がよくわからない方は↓の記事を参考にしてみてください
またRigidbodyを使うにあたってよく使うVector3とQuaternionは↓の記事で解説していますので参考にしてみてください。
<Force Modeの使い方>
Force Modeは力のベクトルを加え方を指定するenum型です。Rigidbodyをスクリプトで動かす際によく使われます。
F(力)= ma (質量×加速度)
a = F / mとなるのが普通ですが、これはこの力のかかり方を変えるものです。
速さを求めるには v = v0 + at なので v = v0 + Ft / m
↓これはAddForceで右側に100の力をかけています。このオブジェクトの質量は全て5です。
↓は力を加えた1フレーム目の速度です。100の力を加えるとこれだけの違いが出ることがわかります。
<Force Modeのスクリプト>
名前空間 | UnityEngine |
型 | enum |
Force
自然の物理法則に最も近い力の掛け方です。
力 = 質量*距離/時間2 → F = ma → a = F / m
という計算の仕方をします。使い方としては、自然と近いので継続的に力を加えていって段々速くなっていく形で使用することが多いです。例えば、FixedUpdateで何秒間力を加え続けるなどです。徐々に加速していく表現等に使用します。
Acceleration
質量を無視した力の掛け方です。
力 = 距離/時間2 → a = F
という計算の仕方をします。Forceとの違いが質量のみなので使い方としては同じです。
Impulse
瞬間的な力のかけ方と言われます。加速を無視していきなり最高速になります。
力 = 質量 * 距離 / 時間 → v = F / m
という計算の仕方をします。かかった力が直接速さに関与していることが見てとれます。
使い方としてはForceとは違い、1度のみ力をかけるような使い方が多いです。
VelocityChange
瞬間的な力のかけ方なのですが、加速を無視していきなり最高速になる上に質量まで無視するため、かけた力はすなわち速度になります。
力 = 距離 / 時間 → v = F
という計算の仕方をします。