はじめに
VR用の衝突判定処理を実装したので、その備忘録メモ。
基本的に、non-VR で実装した処理とほぼ同じで、キャラクター座標は「playerRig」を起点にしていますが、 ルームスケールで動いた場合に座標がズレる問題について、AIに聞いてまとめています。
今回も動画取ってみました。分かりにくいですが衝突判定処理で、停止してます。 ただ、ルームスケールで動くと判定を超えて移動はできます。
概要
VRで衝突判定を実装しようとすると、 non-VRと同じ感覚では必ず混乱する。
- 壁に当たって止まったはずなのに、現実で歩くと壁の向こうに行ける
- UIは押せるのに、移動の当たり判定は別の場所で起きている
- 「リグの位置で判定しているはずなのに?」という違和感
これはバグではなく、VR特有の構造によるもの。
この記事では、 Three.js + WebXR でのVR衝突判定を、 「なぜそう設計するのか」という視点で整理する。
VRには2種類の移動がある
まず、ここを分けないと必ず詰まる。
1. 人工移動(スティック移動)
- コードで制御する移動
playerRig.positionを動かす- 衝突判定の対象
2. 現実移動(ルームスケール)
- 現実の身体の移動
- HMD / コントローラのトラッキング
- 衝突判定の対象外
VRでは、この2つは完全に別レイヤー。
Three.js / WebXR の実際の構造
概念的にはこうなっている。
World
└─ playerRig(人工移動・衝突判定の基準)
└─ XR Reference Space
└─ camera / controller(現実移動で動く)
重要なのは:
- 現実で歩いても playerRig は動かない
- 動くのは
camera.matrixWorldやcontroller.matrixWorld - 衝突判定は playerRig 基準でしか行えない
なぜ現実移動で衝突判定しないのか
理由は単純で、止められないから。
- 壁があるからといって、頭の移動を止められない
- 視点を強制的に押し戻すとVR酔いする
- 安全面でも危険
そのため、すべてのVRゲームはこう割り切っている。
人工移動は制御する 現実移動は制御しない
これは three.js の制限ではなく、VRというメディアの仕様。
VRで正しい衝突判定の基準
❌ やってはいけない
- カメラ(視点)基準での衝突判定
- コントローラ位置での移動制限
- Matrix4 を使った位置衝突判定
⭕ 正解
- playerRig を身体の代理として扱う
- Box3 で「占有空間」を定義する
- 移動前に予測判定する
Box3 と Matrix4 の役割の違い
ここを混ぜると混乱する。
Box3
- 体積・領域
- 衝突判定
- 「ここに入っていいか」
Matrix4
- 姿勢・向き・変換
- レイキャスト
- UI操作・向き計算
衝突判定に Matrix4 は使わない。 UIレイ用に使うのが正しい。
VR用 衝突判定の基本形
export function checkPreCollisionVR(moveVector) {
const predictedPosition =
config.playerRig.position.clone().add(moveVector);
const playerSize = new THREE.Vector3(0.4, 1.7, 0.4);
const predictedBox = new THREE.Box3();
predictedBox.setFromCenterAndSize(
new THREE.Vector3(
predictedPosition.x,
predictedPosition.y + playerSize.y / 2,
predictedPosition.z
),
playerSize
);
for (const wallBox of config.model.wallBoxes) {
if (predictedBox.intersectsBox(wallBox)) {
return false;
}
}
return true;
}
- 判定基準は playerRig
- 視点の上下揺れは無視
- 「止めるだけ」で反発しない
UIが押せてしまう理由
UI操作は、
controller.matrixWorld- レイキャスト
つまり 現実の手の位置を使っている。
一方で移動衝突判定は、
playerRig.position
このズレは仕様であり、 Meta / SteamVR / PSVR すべて同じ。
違和感への対処方法(完全解決は不可)
できるのは「緩和」だけ。
- 壁に近づいたらフェード
- 当たり判定を少し大きめに
- UIは rig 基準距離に配置
- 視点リセット(Recenter)を用意
「VRボタンで正面を更新」は業界標準。
まとめに近い事実
- VRでは 現実の身体は完全に拘束できない
- 衝突判定は人工移動だけに適用する
- Box3 と Matrix4 は役割が違う
- 違和感はバグではなく理解が進んだ証拠
この構造を理解していれば、 VRでの移動と衝突判定に迷わなくなる。
💬 コメント