コリジョン形状
Collisionコンポーネントは、エンティティに物理的な形状を与えます。rigidbodyコンポーネントと組み合わせるとそのRigidBodyの形状を定義し、単独ではトリガーボリュームとして機能します。形状はエンティティの見た目と一致する必要はなく、通常は一致させるべきではありません。物理エンジンは1秒間に何度も形状同士を判定するため、細かいモデルを囲む単純なボックスやカプセルの方が、すべてのポリゴンをなぞるメッシュより高速かつ安定します。
形状のタイプ
| タイプ | プロパティ | 備考 |
|---|---|---|
| Box | Half Extents | デフォルト。ボックスの幅、高さ、奥行きの半分。0.5, 0.5, 0.5で1ユニットの立方体になります |
| Sphere | Radius | |
| Capsule | Radius、Height、Axis | 両端が丸い円柱で、キャラクターによく使われます。Heightは選択したローカル軸に沿った端から端までの長さです |
| Cylinder | Radius、Height、Axis | |
| Cone | Radius、Height、Axis | |
| Mesh | Model AssetまたはRender Asset、Convex Hull | アセットのジオメトリ。後述のメッシュコライダーを参照 |
| Compound | 子エンティティの形状を1つのボディに組み合わせたもの。後述の複合形状を参照 |
プリミティブ形状はメッシュよりもはるかに低コストでシミュレートできるため、オブジェクトに無理なく合う最も単純な形状を使用してください。Y軸方向に立てたカプセルはキャラクターの標準的な選択です。
- Engine
- Editor
- React
- Web Components
player.addComponent('collision', {
type: 'capsule',
radius: 0.5,
height: 2,
axis: 1 // 0 = X、1 = Y(デフォルト)、2 = Z
});
CollisionコンポーネントのTypeドロップダウンから形状を選びます。その下のフィールドはタイプに応じて変わります。ボックスにはHalf Extents、球にはRadius、カプセル、円柱、円錐にはRadius、Height、Axisが表示されます。
<Collision type="capsule" radius={0.5} height={2} axis={1} />
typeを省略すると、コンポーネントは兄弟の<Render>プリミティブのタイプを使用するため、レンダーボックスにはボックスコライダーが付きます。
<pc-collision type="capsule" radius="0.5" height="2" axis="1"></pc-collision>
メッシュコライダー
メッシュコライダーは、通常はエンティティが描画するものと同じモデルアセットまたはレンダーアセットからジオメトリを取得します。2種類あります。
- トライアングルメッシュ(デフォルト)は、凹んだ部分も含めてジオメトリを正確になぞります。StaticとKinematicのボディ、およびトリガーでのみ使用できます。
- 凸包 (Convex Hull) は、ジオメトリを包含する最小の凸形状で包みます。ボウルの内側のような凹みは失われますが、Dynamicなボディが持てる唯一のメッシュ形状です。
大きなモデルからメッシュ形状を構築するには時間とメモリがかかるため、動くものにはプリミティブや複合形状を優先し、トライアングルメッシュは環境用にとどめてください。
- Engine
- Editor
- React
- Web Components
// 環境:描画に使うレンダーアセットから構築したStaticなトライアングルメッシュ
ground.addComponent('collision', {
type: 'mesh',
renderAsset: groundAsset
});
// Dynamicな小物には凸包が必要
crate.addComponent('collision', {
type: 'mesh',
renderAsset: crateAsset,
convexHull: true
});
TypeをMeshに設定し、Model AssetまたはRender Asset(インポートしたGLBが生成するもの)を割り当てます。形状がDynamicなボディに属する場合はConvex Hullにチェックを入れます。
読み込んだレンダーアセットをrenderAssetプロパティに渡し、DynamicなボディにはconvexHullを設定します。
<Collision type="mesh" renderAsset={crateAsset} convexHull />
ジオメトリを指定する属性はありません。type="mesh"はエンティティ自身の<pc-render>のメッシュを使用するため、読み込んだモデル内の<pc-node>で使うのが自然です。
<pc-model asset="car">
<pc-node name="Body">
<pc-collision type="mesh" convex-hull></pc-collision>
<pc-rigid-body type="dynamic" mass="1200"></pc-rigid-body>
</pc-node>
</pc-model>
形状のオフセット
すべての形状には、エンティティの原点に対して形状を移動させるPosition OffsetとRotation Offsetがあります。例えば原点が足元にあるキャラクターモデルでは、カプセルをその高さの半分だけ持ち上げる必要があります。オフセットを使えば、コライダーをずらすためだけに子エンティティを追加する必要がなくなります。
- Engine
- Editor
- React
- Web Components
// エンティティの原点がキャラクターの足元に来るようにカプセルを持ち上げる
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);
CollisionコンポーネントでPosition OffsetとRotation Offset(度)を設定します。どちらもすべての形状タイプで使用できます。
<Collision type="capsule" radius={0.5} height={2} linearOffset={[0, 1, 0]} angularOffset={[0, 45, 0]} />
<pc-collision type="capsule" radius="0.5" height="2" linear-offset="0 1 0" angular-offset="0 45 0"></pc-collision>
複合形状
複合形状 (Compound) は、エンティティの子のコリジョン形状を1つのボディに組み合わせます。メッシュコライダーを使わずにDynamicなボディに複雑な輪郭を与えられます。椅子を座面、背もたれ、4本の脚のすべてボックスで構成しても、凹面メッシュではできない他のDynamicなボディとの衝突が可能です。複合形状はメッシュ形状よりもはるかに低コストでシミュレートできます。
親はrigidbodyコンポーネントと共に、タイプがCompoundのCollisionコンポーネントを持ちます。各子はプリミティブ形状のCollisionコンポーネントを持ち、親に対する相対的な位置と回転で配置されます。子エンティティ自身にrigidbodyコンポーネントは必要ありません。形状全体を所有するのは親のボディです。独自のrigidbodyコンポーネントを持つ子孫は別のボディとして扱われ、複合形状には含まれません。
- Engine
- Editor
- React
- Web Components
// 親がボディを所有し、子の形状を組み合わせる
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);
親にTypeをCompoundにしたCollisionコンポーネントとRigid Bodyコンポーネントを付けます。部品ごとに子エンティティを追加し、プリミティブタイプのCollisionコンポーネントを付けて、親に対する位置と回転を設定します。

<Entity name="chair">
<Collision type="compound" />
<RigidBody type="dynamic" mass={5} />
<Entity name="seat" position={[0, 0.45, 0]}>
<Collision type="box" halfExtents={[0.25, 0.025, 0.25]} />
</Entity>
</Entity>
<pc-entity name="chair">
<pc-collision type="compound"></pc-collision>
<pc-rigid-body type="dynamic" mass="5"></pc-rigid-body>
<pc-entity name="seat" position="0 0.45 0">
<pc-collision type="box" half-extents="0.25 0.025 0.25"></pc-collision>
</pc-entity>
</pc-entity>

子エンティティは実行時に移動できます。子のトランスフォームが変わると、エンジンは複合形状内のその形状のオフセットを更新し、親のボディをスリープから復帰させます。親エンティティはボディの重心でもあるため、形状の範囲内(通常は中心)に置いてください。そうでない場合、力やトルクが加わったときに、見えないピボットを中心に回転するなど、ボディが不思議な挙動を示す可能性があります。
上の椅子はCompound Physics Shapesチュートリアルプロジェクトのものです。
スケール
プリミティブ形状はエンティティのスケールを無視します。ボックスコライダーは常にワールド単位でのHalf Extentsの大きさなので、エンティティを拡大してもコライダーは大きくなりません。代わりにHalf ExtentsやRadiusを変更してください。メッシュ形状は例外で、構築元のエンティティ(またはモデルノード)のワールドスケールに従います。複合形状の子は、親に対する相対的なローカル位置と回転で配置されます。
形状の可視化
エディターは選択中のエンティティのコリジョン形状をビューポートに輪郭表示するため、形状のサイズやオフセットを確認する最も手早い方法です。どの環境でも、アプリケーションの実行中にすべての形状を見るには、エンジンのrender-physics.jsスクリプトをエンティティに追加し、そのDraw Shapesアトリビュートを有効にします。シーン内の各コリジョン形状が半透明のメッシュとして描画されます。
関連情報
- RigidBody - 形状が属するボディ
- トリガーボリューム - ボディを持たない形状
- Collisionコンポーネント - すべてのプロパティのエディターリファレンス
- CollisionComponent - APIリファレンス
- Compound Physics Shapes - 上記の椅子のチュートリアルプロジェクト