1 Choose hand models

上記から好みの左右の Hand を選び以下のように Sphere の代わりに設定する

2. Add a grabbable GameObject

  • 好みの Ball を Scene に配置する。
  • 以下のように XR Grab Interactable コンポーネントを追加。
    • Prefab が更新されないように unpack してからでもいいかも。
    • Rigidbody がつくのも確認
  • この状態で実行すると、Ray が重なっている状態で Grab (中指トリガー) でボールが手に吸い付いてくる
    • たぶん Right で実行してしまったから。Left は Force Grab が無効だった
  • これは、XR Ray Interactor の Force Grab が有効になっているかららしい
  • これを disable にすると、Ray が重なった位置でボールが吸い付くだけになる

XR Grab Interactable でもボールを手に持ってこれる

  • 上記の XR Grab Interactable で Far Attach ModeNear にしても同じようにボールを遠くから手にもってくることができる
    • デフォルトは Defer To Interactor
  • XR Ray Interactor | XR Interaction Toolkit | 3.4.0
    • Near-Far Interactor が入ったので XR Ray Interactor の方が古い

正しいスケールにする

  • Unity はメートル法
  • Cube を作って Measuring Stick として棒状にしてメジャーにするといい

XR Device Simulator では

  • T/Y で 右/左のコントローラモードにし G で Grab できる

3. Hide hands and disable anchor control

  • 現在の問題は2つ
    • ボールを拾うと、手のモデルに重なってしまう
    • grab して、視点変更にスティック を動かすと、手に持っているものが回転する
      • 手にある状態でくるくると回る

XR Ray Interactor の Manipulate Attach Transform を disable にする

  • これで、スティックを回して視点を変更しても、持っているボールは回らなくなる
  • 手に吸い付くから違和感でるけど、表現としてはいろいろできて面白そう

XR Ray Interactor の Select イベントで手のモデルを消す

  • Select イベントなので Grab しているかどうか
    • XR Grab Interactable と同じという理解でいいんだろうか
    • いずれにしろ、Near-Far Interactor を使うことになるのでいいだろう
  • これで、grab 中は手のモデルが消え、離すとまた手のモデルが表示される

4. Fine-tune the throwing experience

  • ボールを弾む (Bounce) するように
  • あらかじめ PhysicsMaterial_Bounce_Low/High/Medium が用意されているので、Ball の Sphere Collision に割り当てる
  • 床を突き抜けるのを防止するために、Collision Detection を変更
  • 続いて、Ball についている XR Grab Interactable の Movement Type を Kinematic に変更
    • 手に持っている間は、ちゃんと追随してくるように
    • Rigidbody の Kinematic と同じなので衝突はする
  • さらに XR Grab InteractableTrack Position/Rotation にある Smooth Position/Rotation も有効化
    • より滑らかに位置や回転が Interactor に追随する

Collision Detection

どれぐらい正確に衝突を計算し評価できるか。主には高速に移動しているとき。

Unity - Manual: Choose a collision detection mode

1. Discrete(離散)

毎フレームの終端位置だけで衝突判定を行います。

  • デフォルト設定
  • フレーム間の軌跡は考慮しない
  • 高速オブジェクトが薄い壁を**すり抜ける(トンネリング)**可能性がある

使いどころ

  • 低速・静止しているオブジェクト全般
  • 床・壁・家具など動かない環境オブジェクト
  • 処理コストを最小限にしたい大量オブジェクト

2. Continuous(連続)

Rigidbody と 静的コライダー(Static Collider) との間に連続判定を行います。

  • 動いている Rigidbody → 静的な壁・床へのすり抜けを防止
  • 動的 Rigidbody 同士の衝突は Discrete のまま
  • Continuous より軽量

使いどころ

  • 床や壁をすり抜ける心配がある中〜高速の動的オブジェクト
  • 弾丸・投擲物で環境との衝突だけ保証したい場合
  • Dynamic 同士の精密判定は不要なケース

3. Continuous Dynamic(連続ダイナミック)

静的コライダー + Continuous / Continuous Dynamic に設定された動的 Rigidbodyの両方と連続判定します。

  • 動的オブジェクト同士でもすり抜けを防止
  • 最も精度が高い
  • 処理コストも最も高い

使いどころ

  • 高速で動くプレイヤーキャラクター
  • VRコントローラーで振り回す武器(XR Grab と組み合わせて有効)
  • 動的オブジェクト同士の精密な衝突が必要な場面

4. Continuous Speculative(投機的連続)

CCD(Continuous Collision Detection)の近似版で、将来の位置を予測して判定します。

  • 静的・動的コライダー両方に対応
  • Continuous Dynamic より処理コストが低い
  • Kinematic Rigidbody にも適用できる(Continuous Dynamic は不可)
  • まれに**幽霊衝突(Ghost Collision)**が発生することがある

使いどころ

  • Kinematic Rigidbody の高速移動(XR Grab の Kinematic モードと相性◎)
  • コストを抑えつつ動的同士の衝突も対応したい場面
  • モバイル・スタンドアローンVRなどのパフォーマンス制約がある環境

まとめ比較表

DiscreteContinuousContinuous DynamicContinuous Speculative
静的コライダーへのCCD
動的コライダーへのCCD
Kinematic対応
処理コスト最低低〜中
幽霊衝突リスク--あり

選択フローチャート

高速移動する?
├─ No  → Discrete
└─ Yes
    ├─ Kinematic Rigidbody?
    │   └─ Yes → Continuous Speculative
    └─ Dynamic Rigidbody?
        ├─ 動的オブジェクト同士の精密判定が必要?
        │   ├─ Yes(コスト許容)→ Continuous Dynamic
        │   └─ Yes(コスト節約)→ Continuous Speculative
        └─ 環境との衝突だけでよい?
            └─ Yes → Continuous

XR Grab Interactable との組み合わせ推奨

Movement Type推奨 Collision Detection
InstantaneousDiscrete(物理無視のため不要)
KinematicContinuous Speculative(Kinematic対応のCCD)
Velocity TrackingContinuous Dynamic(動的同士の精密判定)

Movement Type

XR Grab Interactable | XR Interaction Toolkit | 3.4.0

1. Instantaneous(瞬間移動)

手の位置・回転に毎フレーム直接同期します。

  • transform.position / transform.rotation を直接書き換える
  • 物理演算を完全に無視する
  • Rigidbody があっても衝突を貫通する可能性がある

使いどころ

  • UIパネルや地図など、物理的リアリティが不要なオブジェクト
  • 壁をすり抜けても問題ない軽量なオブジェクト
  • パフォーマンスを優先したい場合

2. Kinematic(キネマティック)

Rigidbody.MovePosition / MoveRotation を使って移動します。

  • Rigidbody を Kinematic モードに切り替えて移動
  • 衝突判定は維持されるが、力による物理応答はしない
  • 壁をすり抜けにくいが、強引に押し込むこともできてしまう

使いどころ

  • ドアのハンドルや引き出しなど、ある程度の衝突を考慮したいもの
  • 重い物体の演出(慣性なしで持てる)
  • Instantaneous より物理的だが、Velocity Tracking より軽い場合

3. Velocity Tracking(速度追従)

Rigidbody に速度・角速度を与えて目標位置へ追従させます。

  • Rigidbody.velocity / angularVelocity を毎フレーム計算して設定
  • 完全な物理演算が維持される
  • 壁に押し当てると止まり、投げると慣性が乗る

使いどころ

  • 剣・銃・ボールなど、リアルな物理挙動が重要なオブジェクト
  • 投擲・振り回しに物理的な重さを感じさせたい場合
  • 他のRigidbodyと正確に衝突させたい場合

まとめ比較表

InstantaneousKinematicVelocity Tracking
移動方法Transform直接MovePositionvelocity設定
衝突判定❌ 弱い⚠️ 部分的✅ 完全
投げの慣性
処理コスト
主な用途UI・軽量オブジェクトドア・レバー類武器・投擲物

選択フローチャート

物理演算が必要?
├─ No  → Instantaneous
└─ Yes
    ├─ 投げたい・慣性が必要?
    │   └─ Yes → Velocity Tracking
    └─ No(衝突だけ考慮したい)
        └─ Kinematic

5. Add a GameObject with a handle

これまではボールを掴んでいたので、場所や回転はどうでもよかったが、ここではより正確な場所や回転で握る

  • 以下から Tennis_Racket_ を取って、シーンのボールの横におく
  • Ball の時と同じく設定を行う
    • XR Grab Interactable をアタッチ
    • Rb の Collision DetectionContenious Dynmic
    • XR Grab Interactable の Smooth Position/Rotation を有効化
    • ⚠️ XR Grab Interactable の Movement Type は Kinemtatic にしない
  • 握るための Attach ポイントを作る
    • ラケットの子として Empty Object を作り、以下のように回転させる
    • local の Y が柄の上の方に向くように
    • ラケットの XR Grab Interactable の Attach Transform に Attach GameObject をセット

ここまでで、左手でボール、右手でラケットを持ってボールをラケットに乗せて遊べるが、自分の環境だと、すぐにすり抜けてしまう。1回ラケットの上で弾ませられるぐらい。これは PC の性能だろうか。