コライダーとボディコンポーネント
はじめに
Quantum 2では、衝突と物理動作のそれぞれに独自のコンポーネントがあります。
- PhysicsCollider2D/PhysicsCollider3Dをエンティティに追加すると、エンティティが動的な障害物またはトリガーになり、そのTransformによって移動できます。
- PhysicsBody2D/PhysicsBody3Dを追加すると、エンティティを物理ソルバーで制御できます。
必要条件
Transform2D/Transform3D、PhysicsCollider2D/PhysicsCollider3DおよびPhysicsBody2D/PhysicsBody3Dコンポーネントは密接に絡み合っています。他が機能するための要件になる場合もあります。依存関係のリストは以下です:
必要条件 | Transform | PhysicsCollider | PhysicsBody | |
---|---|---|---|---|
コンポーネント | ||||
Transform | ✓ | ✗ | ✗ | |
PhysicsCollider | ✓ | ✓ | ✗ | |
PhysicsBody | ✓ | ✓ | ✓ |
これらの依存関係は相互に構築されるため、PhysicsBodyを有効にするためには次の順序でコンポーネントをエンティティに追加する必要があります。
- Transform
- PhysicsCollider
- PhysicsBody
PhysicsBody コンポーネント
PhysicsBody ECSコンポーネントをエンティティに追加すると、エンティティが物理エンジンに認識されます。N.B.: PhysicsBody_を使用するには、エンティティに_Transform_と_PhysicsCollider_が既に存在している必要があります。
コンポーネントは、コードで手動で作成するか、UnityのEntityPrototypeコンポーネントを介して初期化できます。
C#
var entity = f.Create();
var transform = new Transform2D();
var collider = PhysicsCollider2D.Create(f, Shape2D.CreateCircle(1));
var body = PhysicsBody2D.CreateDynamic(1);
f.Set(entity, transform);
f.Set(entity, collider);
f.Set(entity, body);
3D物理の場合も同じです。
C#
var entity = f.Create();
var transform = Transform3D.Create();
var shape = Shape3D.CreateSphere(FP._1);
var collider = PhysicsCollider3D.Create(shape);
var body = PhysicsBody3D.CreateDynamic(FP._1);
f.Set(entity, transform);
f.Set(entity, collider);
f.Set(entity, body);
EntityPrototypeメソッドの場合、コンポーネントは保存された値で初期化されます。
PhysicsCollider3Dは、動的エンティティの次のShape3Dのみに対応しています。
- Sphere
- Box
Center of Mass
Center of Mass(または_CoM_)は、PhysicsBodyコンポーネント上で設定できます。CoMは、Transformコンポーネントで指定した位置からの相対的なオフセットを表します。CoMの位置を変更すると、PhysicsBodyにどのように力を加えるかを変更できます。
デフォルトでは、CoMはPhysicsColliderの形状のセントロイドに設定されています。これは、PhysicsBody ConfigドロワーのReset Center of Mass On Added
によって強制されます。
注: CoMの位置をカスタマイズするには、Reset Center of Mass On Added
フラグのチェックを外す必要があります。そうしないと、PhysicsBodyコンポーネントがエンティティに追加されたときに、CoMはColliderのセントロイドにリセットされてしまいます。
上記の設定は、一様に密度の高いボディ、つまり、一様に密度の高いボディのように振る舞う実体で一般的に用いられています。しかし、CoMとコライダーオフセットは別々に設定されます。以下の表でその組み合わせを説明します。
PhysicsCollider オフセット | PhysicsBody CoM | 追加したフラグのCenter of Massをリセット | 結果の位置 |
---|---|---|---|
デフォルトの位置 = 0, 0, 0 カスタム値 = デフォルトの位置と異なる位置 |
|||
デフォルト位置 | デフォルト位置 | On / Off | コライダーのセントロイドとCoMの位置は、両方とも変換位置に等しいです。 |
カスタム値 | デフォルト位置 | On | Collider Centroidは変換からオフセットされていて、CoMはCollider Centroidの位置と等しい。 |
カスタム値 | デフォルト位置 | Off | Collider Centroidは変換位置からオフセットされていて、CoMは変換位置と等しい。 |
カスタム値 | カスタム位置 | On | Collider Centroidは変換位置からオフセットされていて、CoMはCollider Centroidの位置と等しい。 |
カスタム値 | カスタム位置 | Off | Collider Centroidは変換位置からオフセットされていて、CoMは変換位置からオフセットされています。 |
複合コライダーCoM
複合形状のCoMは、面積(2D)または体積(3D)の加重平均に基づいて、形状のすべての要素の中心点の組み合わせです。
重要なポイント
以下がCoMの設定に関する注意点です。
- PhysicsColliderのオフセットとPhysicsBodyのCoM位置は、互いに区別されています。
- デフォルトでは、PhysicsBody Configには
Reset Center of Mass On Added
とReset Inertia on Added
というフラグがあります。 - カスタムCoMを設定するには、PhysicsBody Configの
Reset Center of Mass On Added
フラグのチェックを外します。 - PhysicsBody Configで
Reset Center of Mass On Added
フラグがチェックされている場合、エディタで指定されたCoMの位置に関係なく、エンティティに追加されると同時にCoMは自動的にPhysicsColliderのセントロイドに設定されます。
外力の適用
PhysicsBody APIでは、外力をボディに手動で適用することができます。
C#
// This is the 3D API, the 2D one is identical.
public void AddTorque(FPVector3 amount)
public void AddAngularImpulse(FPVector3 amount)
public void AddForce(FPVector3 amount, FPVector3? relativePoint = null)
public void AddLinearImpulse(FPVector3 amount, FPVector3? relativePoint = null)
// relativePoint is a vector from the body's center of mass to the point where the force is being applied, both in world space.
// If a relativePoint is provided, the resulting Torque is computed and applied.
public void AddForceAtPosition(FPVector3 force, FPVector3 position, Transform3D* transform)
public void AddImpulseAtPosition(FPVector3 force, FPVector3 position, Transform3D* transform)
// Applies the force/impulse at the position specified while taking into account the CoM.
APIから分かるように、PhysicsBodyの角運動量と線形運動量は、以下を適用することで影響を受けます。
- Force または
- Impulse
これらは似ていますが、重要な違いがあります。forces__は一定期間適用されますが、 impulses__は即時です。これらは次のように考えることができます。
-Force=デルタタイムごとの力
-Impulse=フレームごとの力
Note: In Quantum deltatime is fixed and depended on the simulation rate set in Simulation Config
asset.
impulse__は、シミュレーションレートに関係なく同じ効果をもたらします。しかし、__force__はシミュレーションレートに依存します。つまり、シミュレーションレートが30の時に1のforceベクトルをボディに適用し、シミュレーションレートを60に上げると、デルタタイムは半分になり、その結果、統合されたforceも半分になります。
一般的に言えば、時間厳守で即時の変化を起こす場合には__impulse__を使用することをお勧めします。一方、__force__は常に、徐々に、または長い期間にわたって適用される力に使用するべきです。
コンポーネントの初期化
PhysicsBody をDynamicまたはKinematicなボディとして初期化するには、それぞれのCreate機能を使用できます。これらのメソッドには、PhysicsBody2D
およびPhysicsBody3D
クラスからアクセス可能です。以下がその例です:
- PhysicsBody3D.CreateDynamic
- PhysicsBody3D.CreateKinematic
ShapeConfigs
データ駆動型設計を介してPhysicsColliderとPhysicsBodyを初期化するには、ShapeConfig タイプ(Shape2DConfig、およびShape3DConfig)を使用できます。これらの構造体は、Unityから編集可能な任意のQuantumデータアセットにプロパティとして追加できます(形状、サイズなど)。
C#
// data asset containing a shape config property
partial class CharacterSpec {
// this will be edited from Unity
public Shape2DConfig Shape2D;
public Shape3DConfig Shape3D;
public FP Mass;
}
ボディを初期化するとき、シェイプの代わりにシェイプ設定を直接使用します:
C#
// instantiating a player entity from the Frame object
var playerPrototype = f.FindAsset<EntityPrototype>(PLAYER_PROTOTYPE_PATH);
var playerEntity = playerPrototype.Container.CreateEntity(f);
var playerSpec = f.FindAsset<CharacterSpec>("PlayerSpec");
var transform = Transform2D.Create();
var collider = PhysicsCollider2D.Create(playerSpec.Shape2D.CreateShape(f));
var body = PhysicsBody2D.CreateDynamic(playerSpec.Mass);
// or the 3D equivalent:
var transform = Transform3D.Create();
var collider = PhysicsCollider3D.Create(playerSpec.Shape3D.CreateShape())
var body = PhysicsBody3D.CreateDynamic(playerSpec.Mass);
// Set the component data
f.Set(playerEntity, transform);
f.Set(playerEntity, collider);
f.Set(playerEntity, body);
物理コールバックを有効にする
エンティティには、一連の物理コールバックを関連付けることができます。これらは、コードまたは Entity Prototype の PhysicsCollider コンポーネントで有効にすることができます。
コードで物理コールバックを設定する方法と、それぞれの信号を 実施 する方法については、物理マニュアルの コールバック エントリを参照してください。
キネマティック
Quantum v2では、物理エンティティにキネマティックな挙動をさせるための4つの方法があります。
PhysicsCollider
コンポーネント のみ を保持する。この場合、エンティティには PhysicsBody コンポーネントがありません。つまり質量、抗力、力またはトルクの統合などはありません。任意でエンティティの変換を操作できますが、動体に衝突した場合に衝突の衝撃は、そのエンティティが不動であるかのように解消されます(線速度と角速度がゼロに設定されます)。PhysicsBody
コンポーネント を非有効化する。PhysicsBody 上のIsEnabled
プロパティを false に設定している場合、物理エンジンはそのエンティティを上記1と同様とみなします。力も速度も統合されません。この設定は、ボディを 一時的に 不動のエンティティの挙動として扱いたく、また後にそのボディの設定(質量、抗力係数など)を再度有効化したい場合に適しています。PhysicsBody
コンポーネント 上のIsKinematic
プロパティを true に設定する。この場合、物理エンジンは PhysicsBody 自体には作用しません。ただし、ボディの線速度と角速度は、衝突を解消する際に 他のボディ に作用します。物理エンジンに管理させるのではなく、自分でエンティティの移動を管理したい場合にはこの設定を使用してください。エンティティの移動に責任を担っている点やボディの速度を手動で管理している点、また他の動体をそのエンティティに反応させている点に留意してください。PhysicsBody
をCreateKinematic
で 初期化する。ライフタイム全体を通じて、ボディがキネマティックのように挙動すると予期される場合には、そのボディをキネマティックなボディとして作成できます。これは、上記3に記載した PhysicsBody の挙動を最初から伴います。このボディが動的になる場合には、そのボディをCreateDynamic
メソッドで作成し、IsKinematic = true
に設定してください。IsKinematic をtrueまたはfalseに、また PhysiscBody コンポーネントの再初期化を動的またはキネマティックにする設定は、シームレスにいつでもおこなえます。
PhysicsColliderコンポーネント
コンポーネントを無効化・有効化する
Quantum 2.1以降では、PhysicsCollider
コンポーネントにEnabled
プロパティが備えられています。このプロパティをfalse
に設定する場合、PhysicsSystem
のPhysicsCollider
を持つエンティティは無視されます。
PhysicsBody
は 有効なPhysicsCollider
を必要とするため、これも事実上無効となります。
実行時にShapeを変更する
初期化された後に PhysicsCollider のShapeを変更することができます。
C#
var collider = f.Get<PhysicsCollider3D>(entity);
collider.Shape = myNewShape;
f.Set(entity, collider);
__PhysicsBody__が最初に追加されると、PhysicsColliderの形状を元に慣性とCoMを計算します。そのため、コライダーの形状を変更した後は ResetInertia
とResetCenterOfMass
を呼び出すことを推奨します。
C#
// following the snippet above
var body = f.Get<PhysicsBody3D>(entity);
body.ResetCenterOfMass(f, entity); // Needs to be called first
body.ResetInertia(f, entity); // Needs to be called second
f.Set(entity, body);
特に ResetCenterOfMass
は、古い形状と新しい形状の両方または一方で以下のいずれかがtrueである場合に呼び出すべきです。
- 形状の位置がオフセットされている
- 形が複合した形をしている
- CoMにオフセットがある