メインコンテンツまでスキップ

コリジョン形状

Collisionコンポーネントは、エンティティに物理的な形状を与えます。rigidbodyコンポーネントと組み合わせるとそのRigidBodyの形状を定義し、単独ではトリガーボリュームとして機能します。形状はエンティティの見た目と一致する必要はなく、通常は一致させるべきではありません。物理エンジンは1秒間に何度も形状同士を判定するため、細かいモデルを囲む単純なボックスやカプセルの方が、すべてのポリゴンをなぞるメッシュより高速かつ安定します。

形状のタイプ

タイププロパティ備考
BoxHalf Extentsデフォルト。ボックスの幅、高さ、奥行きの半分。0.5, 0.5, 0.5で1ユニットの立方体になります
SphereRadius
CapsuleRadius、Height、Axis両端が丸い円柱で、キャラクターによく使われます。Heightは選択したローカル軸に沿った端から端までの長さです
CylinderRadius、Height、Axis
ConeRadius、Height、Axis
MeshModel AssetまたはRender Asset、Convex Hullアセットのジオメトリ。後述のメッシュコライダーを参照
Compound子エンティティの形状を1つのボディに組み合わせたもの。後述の複合形状を参照

プリミティブ形状はメッシュよりもはるかに低コストでシミュレートできるため、オブジェクトに無理なく合う最も単純な形状を使用してください。Y軸方向に立てたカプセルはキャラクターの標準的な選択です。

player.addComponent('collision', {
type: 'capsule',
radius: 0.5,
height: 2,
axis: 1 // 0 = X、1 = Y(デフォルト)、2 = Z
});

メッシュコライダー

メッシュコライダーは、通常はエンティティが描画するものと同じモデルアセットまたはレンダーアセットからジオメトリを取得します。2種類あります。

  • トライアングルメッシュ(デフォルト)は、凹んだ部分も含めてジオメトリを正確になぞります。StaticとKinematicのボディ、およびトリガーでのみ使用できます。
  • 凸包 (Convex Hull) は、ジオメトリを包含する最小の凸形状で包みます。ボウルの内側のような凹みは失われますが、Dynamicなボディが持てる唯一のメッシュ形状です。

大きなモデルからメッシュ形状を構築するには時間とメモリがかかるため、動くものにはプリミティブや複合形状を優先し、トライアングルメッシュは環境用にとどめてください。

// 環境:描画に使うレンダーアセットから構築したStaticなトライアングルメッシュ
ground.addComponent('collision', {
type: 'mesh',
renderAsset: groundAsset
});

// Dynamicな小物には凸包が必要
crate.addComponent('collision', {
type: 'mesh',
renderAsset: crateAsset,
convexHull: true
});

形状のオフセット

すべての形状には、エンティティの原点に対して形状を移動させるPosition OffsetRotation Offsetがあります。例えば原点が足元にあるキャラクターモデルでは、カプセルをその高さの半分だけ持ち上げる必要があります。オフセットを使えば、コライダーをずらすためだけに子エンティティを追加する必要がなくなります。

// エンティティの原点がキャラクターの足元に来るようにカプセルを持ち上げる
player.addComponent('collision', {
type: 'capsule',
radius: 0.5,
height: 2,
linearOffset: new pc.Vec3(0, 1, 0)
});

// エンティティのY軸を中心にボックスを45度傾ける
crate.collision.angularOffset = new pc.Quat().setFromEulerAngles(0, 45, 0);
Offset Collision

複合形状

複合形状 (Compound) は、エンティティの子のコリジョン形状を1つのボディに組み合わせます。メッシュコライダーを使わずにDynamicなボディに複雑な輪郭を与えられます。椅子を座面、背もたれ、4本の脚のすべてボックスで構成しても、凹面メッシュではできない他のDynamicなボディとの衝突が可能です。複合形状はメッシュ形状よりもはるかに低コストでシミュレートできます。

親はrigidbodyコンポーネントと共に、タイプがCompoundのCollisionコンポーネントを持ちます。各子はプリミティブ形状のCollisionコンポーネントを持ち、親に対する相対的な位置と回転で配置されます。子エンティティ自身にrigidbodyコンポーネントは必要ありません。形状全体を所有するのは親のボディです。独自のrigidbodyコンポーネントを持つ子孫は別のボディとして扱われ、複合形状には含まれません。

// 親がボディを所有し、子の形状を組み合わせる
const chair = new pc.Entity('chair');
chair.addComponent('collision', { type: 'compound' });
chair.addComponent('rigidbody', { type: pc.BODYTYPE_DYNAMIC, mass: 5 });

// 子が形状を持ち、親に対する相対位置に配置される。rigidbodyは不要
const seat = new pc.Entity('seat');
seat.addComponent('collision', { type: 'box', halfExtents: new pc.Vec3(0.25, 0.025, 0.25) });
seat.setLocalPosition(0, 0.45, 0);
chair.addChild(seat);

Compound shapes chair

子エンティティは実行時に移動できます。子のトランスフォームが変わると、エンジンは複合形状内のその形状のオフセットを更新し、親のボディをスリープから復帰させます。親エンティティはボディの重心でもあるため、形状の範囲内(通常は中心)に置いてください。そうでない場合、力やトルクが加わったときに、見えないピボットを中心に回転するなど、ボディが不思議な挙動を示す可能性があります。

Compound Collision

上の椅子はCompound Physics Shapesチュートリアルプロジェクトのものです。

スケール

プリミティブ形状はエンティティのスケールを無視します。ボックスコライダーは常にワールド単位でのHalf Extentsの大きさなので、エンティティを拡大してもコライダーは大きくなりません。代わりにHalf ExtentsやRadiusを変更してください。メッシュ形状は例外で、構築元のエンティティ(またはモデルノード)のワールドスケールに従います。複合形状の子は、親に対する相対的なローカル位置と回転で配置されます。

形状の可視化

エディターは選択中のエンティティのコリジョン形状をビューポートに輪郭表示するため、形状のサイズやオフセットを確認する最も手早い方法です。どの環境でも、アプリケーションの実行中にすべての形状を見るには、エンジンのrender-physics.jsスクリプトをエンティティに追加し、そのDraw Shapesアトリビュートを有効にします。シーン内の各コリジョン形状が半透明のメッシュとして描画されます。

関連情報