This document is about: QUANTUM 3
SWITCH TO

コライダーおよびボディコンポーネント

はじめに

衝突と物理挙動は、それぞれQuantum 2において独自のコンポーネントを持っています。

  • エンティティにPhysicsCollider2D/PhysicsCollider3Dを追加すると、そのエンティティはダイナミックな障害物やトリガーになり、トランスフォームを介して移動できるようになります。
  • PhysicsBody2D/PhysicsBody3Dを追加すると、そのエンティティは物理ソルバーによって制御されるようになります。

要件

Transform2D/Transform3D、PhysicsCollider2D/PhysicsCollider3D、PhysicsBody2D/PhysicsBody3Dコンポーネントは密接に関連しています。そのため、いくつかのコンポーネントは他のコンポーネントが機能するための要件となります。完全な依存関係のリストは以下に示されています。

Requirement Transform PhysicsCollider PhysicsBody
コンポ―ネント
トランスフォーム
PhysicsCollider
PhysicsBody

これらの依存関係は相互に関連しており、PhysicsBodyを有効にするためには、次の順序でコンポーネントをエンティティに追加する必要があります:

  1. Transform
  2. PhysicsCollider
  3. PhysicsBody

衝突コールバックの詳細はこちらをご覧ください。

PhysicsBodyコンポーネント

エンティティにPhysicsBody ECSコンポーネントを追加すると、そのエンティティは物理エンジンによって考慮されるようになります。注: PhysicsBodyを使用するには、エンティティがすでにTransformおよびPhysicsColliderを持っている必要があります。

コンポーネントは、コード内で手動で作成および初期化することも、UnityのQuantumEntityPrototypeコンポーネントを介して行うことも可能です。

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);

QuantumEntityPrototypeの代替手段を使用する場合、コンポーネントはUnityインスペクターで定義された値で初期化されます。

Adjusting a Quantum Entity Prototype's Physics Properties via the Unity Editor
Adjusting an Entity Prototype's Physics Properties via the Unity Editor.

ダイナミクスのためのサポートされている形状

PhysicsCollider3Dは、ダイナミックエンティティに対して以下のShape3Dのみをサポートしています:

  • スフィア(Sphere)
  • ボックス(Box)
  • カプセル(Capsule)
  • コンパウンド(Compound、複数の形状の組み合わせ)

エディタでは、Unityのカプセルと同じプロパティである半径(Radius)と高さ(Height)を使用してカプセル形状のプロパティを設定できます。しかし、内部的にはQuantumではカプセルを半径(Radius)とエクステント(Extent)として定義しています。また、高さ(Height)と直径(Diameter)に関するプロパティもあります。

PhysicsCollider2Dは、ダイナミックエンティティに対して以下のShape2Dのみをサポートしています:

  • サークル(Circle)
  • ボックス(Box)
  • ポリゴン(Polygon)
  • エッジ(Edge)
  • カプセル(Capsule)
  • コンパウンド(Compound、複数の形状の組み合わせ)

以下は、使用できるカプセルコライダーに関連するいくつかのコードスニペットです。

C#

FP radius = FP._0_50;
FP extent = FP._1;
Shape2D shape = Shape2D.CreateCapsule(radius, extent);

// Draw the capsule
Draw.Capsule(FPVector2.Zero, shape.Capsule);
Draw.Capsule(FPVector2.Zero, extent, radius);

以下の画像は、明確にするためにQuantumのカプセルコライダーとUnityのカプセルコライダーの意味的な違いを示しています。

Difference between Unity's capsules and Quantum's capsules
UnityのカプセルとQuantumのカプセルの違い。

重心

Center of Mass(重心)は、以降 CoM と呼ばれ、PhysicsBodyコンポーネントで設定できます。CoMは、トランスフォームコンポーネントで指定された位置に対するオフセットを表します。CoMの位置を変更することで、PhysicsBodyに対してどのように力が作用するかに影響を与えることができます。

Animated examples of how various CoM affect the same PhysicsBody
同じPhysicsBodyに対してさまざまなCoMがどのように影響を与えるかを示すアニメーション例。

デフォルトでは、CoMはPhysicsColliderの形状の重心に設定されています。これはPhysicsBody Configドロワーの Reset Center of Mass On Added によって強制されます。

注: CoMの位置をカスタマイズするには、 Reset Center of Mass On Added フラグのチェックを外すことが必要です。これを外さないと、PhysicsBodyコンポーネントがエンティティに追加されると、CoMはコライダーの重心にリセットされてしまいます。

Defaults Flags in the PhysicsBody Config
Unityエディタで表示されるPhysicsBody Configのデフォルトフラグ。

上記の構成は、均一な密度のボディ、つまり均一密度を持つボディのように振る舞うエンティティの一般的な設定です。ただし、CoMとコライダーのオフセットは別々に設定されています。組み合わせについては、以下の表で説明しています。

PhysicsCollider Offset PhysicsBody CoM Center of Mass On Addedフラグのリセット 結果となる位置
デフォルトの位置 = 0, 0, 0
カスタム値 = デフォルトの位置とは異なるいかなる位置
デフォルトの位置 デフォルトの位置 オン / オフ コライダーの重心とCoMの位置はトランスフォーム位置に対して両方とも同じです。
カスタム値 デフォルトの位置 オン コライダーの重心はトランスフォームから オフセットされ、CoMはコライダーの重心位置に対して同等です。
カスタム値 デフォルトの位置 オフ コライダーの重心はトランスフォームの位置から オフセットされ、ます。
CoMはトランスフォームの位置に対して同等です。
カスタム値 カスタム位置 オン コライダーの重心はトランスフォームの位置からオフセットされます。
CoMはコライダーの重心の位置に対して 同等です。
カスタム値 カスタム位置 オフ コライダーの重心はトランスフォームの位置からオフセットされます。
CoMはトランスフォームの位置からオフセットされます。

複合コライダーのCoM

複合形状のCoMは、すべての形状要素の重心の組み合わせであり、それぞれの面積(2D)または体積(3D)の重み付き平均に基づいています。

重要なポイント

要約すると、CoM設定に関する主なポイントは次のとおりです。

  1. PhysicsColliderのオフセットとPhysicsBodyのCoM位置は別々です。
  2. デフォルトでは、PhysicsBody Configには Reset Center of Mass On AddedReset Inertia on Added のフラグが設定されています。
  3. カスタムCoMを設定するには、PhysicsBody Configで Reset Center of Mass On Added フラグのチェックを外します。
  4. PhysicsBody Configで Reset Center of Mass On Added フラグがチェックされている場合、CoMはエンティティに追加される際にPhysicsColliderの重心に自動的に設定されます。これはエディタで指定されたCoM位置に関係ありません。

外部力の適用

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.

物理ボディの角運動量および線運動量は、次の方法で影響を受けることがあります:

  • 力(forces); または
  • インパルス(impulses).

これらは似ていますが、重要な違いがあります。__力__は時間の経過に対して適用されるのに対し、__インパルス__は即時に作用します。これらは次のように考えることができます:

  • 力 = 力 ÷ デルタ時間
  • インパルス = 力 ÷ フレーム

注: QuantumではΔtは固定されており、Simulation Configアセットで設定されたシミュレーションレートに依存しています。

__インパルス__はシミュレーションレートに関係なく同じ効果をもたらします。しかし、__力__はシミュレーションレートに依存します。これは、シミュレーションレートが30の時にボディに対して1の力ベクトルを適用した場合、シミュレーションレートを60に増加させるとΔtが半分になり、したがって統合された力も半分になることを意味します。

一般的には、__インパルス__を使用するのが望ましいのは、瞬間的かつ即時の変化を意図している場合であり、__力__は常に、徐々に、または長い期間にわたって適用されるものに使用すべきです。

コンポーネントの初期化

PhysicsBody をダイナミックボディまたはキネマティックボディとして初期化するには、それぞれのCreate関数を使用します。これらのメソッドは PhysicsBody2D および PhysicsBody3D クラスからアクセス可能です。例えば以下の2つです。

  • 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.CreateKinematic(playerSpec.Mass);

// or the 3D equivalent:
var transform = Transform3D.Create();
var collider = PhysicsCollider3D.Create(playerSpec.Shape3D.CreateShape())
var body = PhysicsBody3D.CreateKinematic(playerSpec.Mass);

// Set the component data
f.Set(playerEntity, transform);
f.Set(playerEntity, collider);
f.Set(playerEntity, body);

物理コールバックの有効化

エンティティには、それに関連付けられた一連の物理コールバックを持たせることができます。これらはコードを介して、またはQuantum Entity PrototypePhysicsColliderコンポーネントで有効にすることができます。

Setting Physics Callbacks via the Entity Prototype's Physics Properties in the Unity Editor
Unityエディタ内のQuantum Entity Prototypeの物理プロパティを介して物理コールバックを設定する。

コード内で物理コールバックを設定し、該当するsignalsを__実装__する方法についての情報は、物理マニュアルのCallbacks項目を参照してください。

キネマティック

物理エンティティがキネマティックのような振る舞いをする方法は4つあります:

  1. PhysicsCollider コンポーネントのみを持つこと。この場合、エンティティは*PhysicsBody* コンポーネントを持たず、すなわち質量、ドラッグ、力/トルクの統合などはありません。エンティティのトランスフォームを自由に操作することが可能ですが、ダイナミックボディとの衝突時には、衝突のインパルスはエンティティが静止しているかのように解決されます(直線および角速度がゼロになります)。

  2. PhysicsBody コンポーネントを*無効にすること。PhysicsBody*のIsEnabledプロパティを__false__に設定すると、物理エンジンはエンティティをポイント1で示されるように扱います ― すなわち、コライダーコンポーネントのみを持っているかのように。力や速度は統合されません。これにより、ボディは一時的に静的なエンティティとして振る舞い、後で再度有効にしたときに設定(質量、ドラッグ係数など)を保持するのに適しています。

  3. PhysicsBody コンポーネントIsKinematicプロパティを__true__に設定すること。この場合、物理エンジンは*PhysicsBody*自体に影響を与えませんが、そのボディの線速度および角速度は、衝突を解決する際に他のボディに影響を与えます。これは、物理エンジンにエンティティの動きを任せるのではなく、エンティティの動きを制御するために使用します。エンティティを移動させることや、そのボディの速度を手動で制御する必要がある一方で、他のダイナミックボディが反応することを理解しておく必要があります。

  4. CreateKinematicを使用してPhysicsBodyを*初期化すること。ボディがその生涯を通じてキネマティックとして振る舞うことが期待される場合は、単にキネマティックボディとして作成します。これにより、PhysicsBodyは最初から3のように振る舞います。ボディが最終的にダイナミックボディになる必要がある場合は、CreateDynamicメソッドを使用して新しいボディを作成し、IsKinematic = trueを設定します。IsKinematicをtrue/falseに設定し、PhysicsBody*コンポーネントをダイナミック/キネマティックとして再初期化することは、いつでもシームレスに行うことができます。

PhysicsColliderコンポーネント

コンポーネントの無効化 / 有効化

PhysicsColliderコンポーネントにはEnabledプロパティがあります。このプロパティをfalseに設定すると、PhysicsColliderを持つエンティティはPhysicsSystemにおいて無視されます。

PhysicsBodyは*アクティブ*なPhysicsColliderを必要とするため、実際に無効化されることになります。

実行時に形状を変更する

PhysicsColliderの形状は、初期化後に変更することが可能です。```csharp
var collider = f.Get(entity);
collider.Shape = myNewShape;
f.Set(entity, collider);


*PhysicsBody*が最初に追加されると、PhysicsColliderの形状に基づいて慣性と重心(CoM)が計算されます。そのため、コライダーの形状を変更した後は、`ResetInertia`および`ResetCenterOfMass`を呼び出すことをお勧めします。

```csharp
// 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()` **は必ず最初に**呼び出し、次に`ResetInertia()`を呼び出してください。

特に、以下のいずれかが古い形状または新しい形状に対して真である場合は、ResetCenterOfMassを呼び出す必要があります。

  • 形状に位置オフセットがある
  • 形状が複合形状である
Back to top