0. 本記事の内容
本記事ではXR Interaction Toolkitを使用してMeta Questで3Dオブジェクト(立方体)をつかんで操作するマニピュレーションを実現する方法を紹介します。手やコントローラでオブジェクトを掴み、移動・回転・スケール変更を行う基本的な操作を学習できます。
GitHubで公開しているサンプルのXRI_Samplesプロジェクト、02-Manipulationまたは02-Manipulation-ARシーンでも動作を確認できます。
*この動画はAR版ですが記事の内容はAR/VR両対応です
なお本記事は下記で作成したシーンを編集してマニピュレーション機能を追加します。VRまたはAR機能が設定済みのシーンをご用意ください。
[VR版]
[AR版]
1. シーンの複製
前回の記事で作成したシーンを編集することも可能ですが、既存のシーンを破壊せずにマニピュレーション機能を試すため、シーンを複製する方法を紹介します。不要な場合は読み飛ばしてください。
- 前回までに作成したVR版またはAR版のシーンを開く
-
File -> Save As...をクリックして現在のシーンを新しい名前で保存
*本記事ではManipulationとします - Hierarchyに表示されるシーン名がManipulationになっていることを確認
2. オブジェクトの接触検知を有効化
オブジェクトをつかんで操作するには手やコントローラとオブジェクトとの接触を検知する必要があります。ここで解説するオブジェクトとの接触検知に関する手順は、Quest開発に限らずUnityでの開発に共通する内容となります。
[Colliderの確認]
- Hierarchyで操作対象のオブジェクト(Cube)を選択
- Inspectorで表示されるCubeの詳細情報にBox Colliderが適用されていることを確認
*Cube以外のオブジェクトの場合は、各オブジェクトに合わせたColliderを使用
*自作のモデルの場合は手作業でColliderを追加
[Rigidbodyの追加と設定]
- Inspector下方のAdd Componentボタンをクリック
- 検索領域にRigidbodyと入力
- 表示された候補の中からRigidbodyを選択
- InspectorにRigidbodyが追加されたことを確認し、下記のように変更
設定項目 | 設定値 | 説明 |
---|---|---|
Use Gravity | OFF | 重力の影響を無効化 |
Is Kinematic | ON | 物理演算を無効化 |
重要: 接触検知にはColliderとRigidbodyが必要になるので、必ず対象となるオブジェクトにセットしてください。
3. つかんで操作できる属性の追加
ここではオブジェクトを「つかめる」ようにする、「移動可能」にするという2種類の属性を追加します。
[Interactableコンポーネントの追加]
- HierarchyでCubeを選択
- Add Componentをクリック後、XRGrabInteractableで検索
- 候補の中からXR Grab Interactableを選択
これだけで基本的なマニピュレーション(つかんで移動)が動作します。なおコントローラを使ってオブジェクトをつかむ場合は中指のグリップボタンを使用します。
ただし、現状の設定では手やコントローラでつかんだときにオブジェクトの向きが変更されてしまいます。つかんだ瞬間の位置や向きをキープする場合は下記を追加で設定します。
- Cubeをクリック
- InspectorでUse Dynamic AttachをON
[操作内容のON/OFF(オプション)]
XR Grab Interactableコンポーネント内の下記の項目のチェックを切り替えることで、マニピュレーションによる値の変化の可否を設定できます。
設定項目 | 説明 |
---|---|
Track Position | 位置の変更を有効/無効 |
Track Rotation | 回転の変更を有効/無効 |
Track Scale | スケールの変更を有効/無効 |
*スケール変更を有効化するには次の操作も必要
4. スケール変更の設定(オプション)
両手で操作をする際にオブジェクトのスケールを変更したい場合は下記の設定も行ってください。
[基本設定]
- HierarchyでCubeを選択
- InspectorでXR Grab Interactableを見つける
- Select ModeをMultipleに変更
- Add Componentをクリック後、XRGeneralで検索
- XR General Grab Transformerを追加
- Allow Two Handed ScalingをON
[スケーリング時の回転制御(オプション)]
スケーリング中にオブジェクトを回転させたくない場合は下記のスクリプトを作成して追加してください。
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Interactables;
public class TwoHandsScaleController : MonoBehaviour
{
[SerializeField]
private XRGrabInteractable grabInteractable;
void Start()
{
if (grabInteractable == null)
grabInteractable = GetComponent<XRGrabInteractable>();
if (grabInteractable != null)
{
grabInteractable.selectEntered.AddListener(OnSelectEntered);
grabInteractable.selectExited.AddListener(OnSelectExited);
}
}
private void OnSelectEntered(SelectEnterEventArgs args)
{
CheckGrabCount();
}
private void OnSelectExited(SelectExitEventArgs args)
{
CheckGrabCount();
}
private void CheckGrabCount()
{
int grabCount = grabInteractable.interactorsSelecting.Count;
if (grabCount >= 2)
{
Debug.Log("Grabbed with both hands!");
OnTwoHandGrab();
}
else if (grabCount == 1)
{
Debug.Log("Grabbed with one hand");
OnSingleHandGrab();
}
else
{
Debug.Log("Not grabbed");
OnNoGrab();
}
}
private void OnTwoHandGrab()
{
// 両手でつかんだ時の制御
// スケーリングを有効にし、回転制御を調整
grabInteractable.trackRotation = false; // 両手操作時は回転追跡を無効
grabInteractable.trackPosition = false; // 必要に応じて位置追跡も無効
}
private void OnSingleHandGrab()
{
// 片手でつかんだ時の制御
// 現在は特別な動作は不要
grabInteractable.trackRotation = true;
grabInteractable.trackPosition = true;
}
private void OnNoGrab()
{
// つかんでいない時の制御
// デフォルト状態に復元
grabInteractable.trackRotation = true; // 回転追跡を有効
grabInteractable.trackPosition = true; // 位置追跡を有効
}
void OnDestroy()
{
if (grabInteractable != null)
{
grabInteractable.selectEntered.RemoveListener(OnSelectEntered);
grabInteractable.selectExited.RemoveListener(OnSelectExited);
}
}
}
[スクリプトの適用]
- 上記のスクリプトをTwoHandsScaleController.csとして保存
- Cubeオブジェクトにこのスクリプトをアタッチ
- Grab Interactableフィールドに同じオブジェクトのXR Grab Interactableコンポーネントを設定
5. 動作確認
[基本操作の確認]
- アプリを実行し、コントローラのグリップボタンまたは手でオブジェクトをつかむ
- オブジェクトが手やコントローラの動きに追従することを確認
- 両手でつかんだ場合、スケール変更が可能であることを確認
[操作方法]
操作 | 方法 |
---|---|
つかむ | グリップボタン(コントローラ)/ 手を閉じる(ハンドトラッキング) |
移動 | つかんだ状態で手やコントローラを移動 |
回転 | つかんだ状態で手やコントローラを回転 |
スケール | 両手でつかんで手の距離を変更 |
6. 次のステップ
ここまでの操作でコントローラや手につかまれた場合にオブジェクト(Cube)の位置・角度・スケールが変更されるという設定が完了しました。次はUIの操作方法についても紹介します。