トリガーボリューム
トリガーボリュームは、RigidBodyがボリューム内に入ったり出たりしたときにイベントを発生させるコリジョン形状で、何かを物理的に遮ることはありません。サッカーの試合でゴールが決まったとき、レースカーがゴールラインを越えたとき、プレイヤーが部屋に入ったときなどの検出に役立ちます。
トリガーボリュームの作成
トリガーは、rigidbodyコンポーネントを持たないエンティティに付いたCollisionコンポーネントにすぎません。メッシュ形状や複合形状を含め、どのコリジョン形状でも使えます。ボックス型のゴールマウスの例です。
- Engine
- Editor
- React
- Web Components
const goal = new pc.Entity('goal');
goal.addComponent('collision', {
type: 'box',
halfExtents: new pc.Vec3(2, 1, 0.5)
});
goal.setPosition(0, 1, -10);
app.root.addChild(goal);
エンティティにCollisionコンポーネントを追加して形状を設定しますが、Rigid Bodyコンポーネントは追加しないでください。エンティティを選択している間、エディターはビューポートに形状を描画するため、シーンに合わせてボリュームのサイズを調整しやすくなります。
<Entity name="goal" position={[0, 1, -10]}>
<Collision type="box" halfExtents={[2, 1, 0.5]} />
</Entity>
<pc-entity name="goal" position="0 1 -10">
<pc-collision type="box" half-extents="2 1 0.5"></pc-collision>
</pc-entity>
トリガーにはRigidBodyがないため、setPositionやsetRotationなど、Entityの通常のトランスフォームAPIで他のエンティティと同じように移動できます。物理エンジンは次のステップで新しいトランスフォームを取り込みます。
トリガーイベントの監視
トリガーのCollisionコンポーネントは、RigidBodyがボリュームと重なり始めたときにtriggerenterを、重なりが終わったときにtriggerleaveを発火します。どちらのイベントも、出入りしたボディのエンティティを引数として渡します。
goal.collision.on('triggerenter', (entity) => {
console.log(`${entity.name} has entered ${goal.name}.`);
});
goal.collision.on('triggerleave', (entity) => {
console.log(`${entity.name} has left ${goal.name}.`);
});
反対側のRigidBodyも、自身のCollisionコンポーネントとrigidbodyコンポーネントから同じ2つのイベントを受け取ります。そのハンドラーにはトリガーのエンティティが渡されるため、ボディ側で通過したボリュームに反応することもできます。
player.rigidbody.on('triggerenter', (trigger) => {
if (trigger.tags.has('checkpoint')) {
lastCheckpoint = trigger.getPosition().clone();
}
});
購読の方法は衝突イベントとまったく同じです。onはEventHandleを返し、そのoff()メソッドでリスナーを解除できます。同じコールバックをコンポーネントのoff(eventName, callback)に渡して解除することもできます。衝突イベントでは、エディター、React、Web Componentsでそのコードをどこに置くかを示しています。
トリガーを発火させられるもの
トリガーイベントを発火させるのは、DynamicとKinematicのRigidBodyだけです。Staticなボディは決して動かないため重なりの判定から除外され、トリガー同士が互いを検出することもありません。トリガーが発火しないように見える場合は、通過するエンティティにrigidbodyコンポーネントがあり、そのタイプがDynamicまたはKinematicになっているか確認してください。
トリガーとの重なりでは、contact、collisionstart、collisionendイベントは発火しません。これらはRigidBody同士の物理的な接触のためのもので、衝突イベントで説明しています。