開発
開発
プラットフォームを選択

コントローラー入力とトラッキングのスタートガイド

更新日時: 2025/11/10

概要

このチュートリアルは、コントローラー入力をすばやく作動させるための基本参考資料です。Meta Quest TouchとTouch Proコントローラーの機能の追加に関する詳細なドキュメントについては、コントローラーをマップするをご覧ください。コントローラーインタラクションとハンドインタラクションをアプリに追加するライブラリ全体については、Interaction SDKの概要をご覧ください。
App running on a Meta Quest 2
Meta Quest 2で実行するアプリ
このガイドでは、次のことをする方法について説明します。
  • OVRCameraRigをUnityプロジェクトに追加する。
  • ユーザーの入力をコントローラーのインデックスとハンドトリガーを通して受け取る。
  • ユーザーがコントローラーのサムスティックを(左または右に)押したときに入力を受け取る。
  • ユーザーがAボタンを放したときに、ハプティクスフィードバックを提供する。
  • コントローラーの位置と回転情報(6DOF)を受け取る。
: このチュートリアルでは、Unityエディター バージョン2021.3.20f1とMeta XRオールインワンSDK v59を使っています。他のバージョンを使っている場合はスクリーンショットが異なることがありますが、機能はほぼ同じです。

前提条件

このチュートリアルを進める前に、Meta Quest VRヘッドセットのUnity Hello Worldに記載された設定ステップを完了し、必要な依存関係を含めてプロジェクトを作成します。これには、Meta Questヘッドセット上で実行できるようにすることが含まれます。このチュートリアルはそのようなプロジェクトに基づき構成されています。

プロジェクトの設定

コントローラー入力のマッピング

次の図は、Meta Quest Touchコントローラー(Meta Quest 2)の一般的な入力のマッピングを示します。これらのマッピングは、Meta Quest Touch Proコントローラー(Meta Quest Pro)とMeta Quest Touch Plusコントローラー(Meta Quest 3とMeta Quest 3S)でも使われます。
Input Mapping
以下は、コントローラーを直接公開する未加工のマップです。
Input Raw Mapping
このチュートリアルでは、以下のマッピングについて説明します。
マッピング説明
RawButton.RIndexTrigger
右コントローラーのインデックストリガー
RawButton.RThumbstickLeft
右コントローラーのサムスティックを左に押す
RawButton.RThumbstickRight
右コントローラーのサムスティックを右に押す
Button.One
右コントローラーのAボタン
Axis1D.PrimaryHandTrigger
左コントローラーのハンドトリガー
: Secondaryは右コントローラー、Primaryは左コントローラーです。
これらはすべて、Meta Questコントローラーとゲームパッドの統一された入力システムを提供するOVRInputクラスで提供されています。詳しくは、OVRInputクラスのリファレンスをご覧ください。

実装

OVRCameraRigをシーンに追加する

まだプロジェクトにOVRCameraRigを追加していない場合は、次の手順に従ってください。
Meta XR Core SDKには、OVRCameraRig prefabが含まれています。これは、Unityのデフォルトのメインカメラに代わる機能となります。
以下の手順に従って、OVRCameraRigをシーンに追加します。
  1. プロジェクトの[Hierarchy (階層)]で、[Main Camera (メインカメラ)]を右クリックし、[Delete (削除)]を選択します。
  2. [Project (プロジェクト)]タブで[All Prefabs (すべてのprefab)]を選択し、OVRCameraRigを検索し、OVRCameraRig prefabをプロジェクトの[Hierarchy (階層)]にドラッグします。
  3. [Hierarchy (階層)]の中の[OVRCameraRig]を選択します。
  4. [Inspector (インスペクター)]ウィンドウの[OVR Manager (OVRマネージャ)]コンポーネントで、[Target Devices (ターゲットデバイス)]から該当するヘッドセットを選択します。

コントローラーからの入力を管理する新しいスクリプトを追加する

  1. [Project (プロジェクト)]タブの下で、Assetsフォルダーに移動します。
  2. 右クリックして、[Create (作成)] > [Folder (フォルダ)]を選択し、名前をScriptsにしてから、この新しいフォルダを開きます。
  3. 右クリックして、[Create (作成)] > [C# Script (C#スクリプト)] (またはUnity 6以降の場合は[Create (作成)] > [MonoBehaviour Script (MonoBehaviourスクリプト)])を選択し、ControllerScriptという名前を付けます。
    Add C# script
  4. 新規作成したスクリプトを[Hierarchy (階層)]タブの[Cube (立方体)] GameObjectまでドラッグします。
  5. [Hierarchy (階層)]タブで、Cube GameObjectを選択します。
  6. [Inspector (インスペクター)]で、ControllerScript.csスクリプトをダブルクリックして、使いたいIDEで開きます。
    C# script in Inspector

スクリプトを実装する

ControllerScript.csを実装します。

メンバー変数を追加する

ControllerScriptクラスで、次の変数を追加します。
    public Camera sceneCamera;
    private Vector3 targetPosition;
    private Quaternion targetRotation;
    private float step;
  • sceneCameraは、シーンで使用するカメラを表します。
  • targetPositionはカメラの位置を表します。
  • targetRotationはカメラの回転を表します。
  • stepCube GameObjectにアニメーションを付けるのに役立ちます。

キューブの初期位置をStart()でユーザーの前方に設定する

Start()関数で、キューブの初期位置を定義します。
    void Start()
    {
        transform.position = sceneCamera.transform.position + sceneCamera.transform.forward * 3.0f;
    }
これは最初、Cube GameObjectをユーザーの前方3メートルの距離に置きます。

キューブをスムーズに配置し回転させるヘルパー関数を作成する

この関数はオプションですが、視覚的にアピールするもので、キューブの位置調整と方向調整をアニメーションにするためのアプローチです。新しいcenterCube()関数を作成し、次の行を追加します。
    void centerCube()
    {
        targetPosition = sceneCamera.transform.position + sceneCamera.transform.forward * 3.0f;
        targetRotation = Quaternion.LookRotation(transform.position - sceneCamera.transform.position);

        transform.position = Vector3.Lerp(transform.position, targetPosition, step);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, step);
    }
centerCube()関数は、Cube GameObjectをスムーズにユーザー前方、ビューポートの中央に配置し、ユーザーのヘッドポーズ(カメラ)に従ってキューブを回転させます。
詳しくは、Quaternion.LookRotationVector3.LerpQuaternion.Slerpに関するUnityのドキュメントをご覧ください。

ステップ値を追加する

Update()関数で、キューブにアニメーションを付けるためのステップ値を定義します。
    void Update()
    {
        step = 5.0f * Time.deltaTime;
    }
詳しくは、Time.deltaTimeに関するUnityのドキュメントをご覧ください。

右のインデックストリガーから入力を受け取る

コントローラーの現在の状態をクエリするには、OVRInputのメンバー関数Get()を使用してください。
この単純なインタラクションで、OVRInput.RawButton.RIndexTriggerからブーリアン値を受け取ることができます。これはトリガーを単純なボタンとして扱います。この値がtrueの場合、ユーザーは現在そのトリガーを押しています。つまり、centerCube()関数を呼び出してキューブを配置したり回転させたりできます。
次の行をUpdate()関数に追加します。
        if (OVRInput.Get(OVRInput.RawButton.RIndexTrigger)) centerCube();

右のインデックスサムスティックから入力を受け取る

このインタラクションでは、OVRInput.RawButton.RThumbstickLeft (ユーザーはサムスティックを左に押す)とOVRInput.RawButton.RThumbstickRight (ユーザーはサムスティックを右に押す)が返す浮動小数点値を受け取ります。これらの2つの値のいずれかがtrueの場合は、それに応じてキューブを回転させます。
次の行をUpdate()関数に追加します。
        if (OVRInput.Get(OVRInput.RawButton.RThumbstickLeft)) transform.Rotate(0, 5.0f * step, 0);
        if (OVRInput.Get(OVRInput.RawButton.RThumbstickRight)) transform.Rotate(0, -5.0f * step, 0);

Aボタンから入力を受け取ってハプティクスフィードバックを追加する

ユーザーが(前のフレームで)Aボタンを放したかどうかを確認するには、OVRInputのメンバー関数GetUp()を使用します。
このインタラクションでは、OVRInput.Button.Oneが返すブーリアン値を受け取ります。trueの場合、ユーザーはAボタンをちょうど放したところです。
振動を開始、更新、終了するには、OVRInput.SetControllerVibration(float frequency, float amplitude, Controller controllerMask)として定義されているSetControllerVibration()を呼び出す必要があります。この関数を使う場合は、パラメーターについて以下のことを覚えておいてください。
  • amplitudeの期待値は0以上1以下の値です。
  • amplitudeが大きいほど、振動は強くなります。
  • ハプティクスを有効にするには、frequencyを1に設定する必要があります。
  • controllerMaskは、右コントローラーを表すOVRInput.Controller.RTouchか、左コントローラーを表すOVRInput.Controller.LTouchになります。
  • 振動を終了させるには、amplitudefrequencyの両方を0に設定します。
  • コントローラーの振動は最後の入力から2秒後に自動的に終了します。
ユーザーがAボタンを放した後、右コントローラーのハプティクスフィードバックを2秒間持続させるには、次の行をUpdate()関数に追加してください。
        if (OVRInput.GetUp(OVRInput.Button.One))
        {
            OVRInput.SetControllerVibration(1, 1, OVRInput.Controller.RTouch);
        }

左手のトリガーから入力を受け取る

: これはコントローラーのトリガーであって、実際のユーザーの手のトリガーではありません。
このインタラクションでは、OVRInput.Axis1D.PrimaryHandTrigger (ユーザーが手のトリガーを押す)が返す浮動小数点値を受け取ります。
返り値が0.0fより大きい間は、キューブをOVRInput.GetLocalControllerPosition()によって左コントローラーの位置に置き、OVRInput.GetLocalControllerRotation()によって左コントローラーの回転に従って回転させます。どちらもコントローラーを表すパラメーターを受け付けます。
次の行をUpdate()関数に追加し、スクリプトを保存します。
        if (OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger) > 0.0f)
        {
            transform.position = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch);
            transform.rotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch);
        }

インスペクターでカメラをコントローラースクリプトにアタッチする

OVRcameraRigを使って、カメラのポーズをユーザーの左目、右目、両目の平均のいずれかに設定することを選択できます。
  1. Unityエディターを開き、[Hierarchy (階層)]タブでCube GameObjectを選択します。
  2. [Inspector (インスペクター)]で、[Controller Script (コントローラースクリプト)]コンポーネントにフォーカスし、[Scene Camera (シーンカメラ)]の隣にある選択ツールをクリックします。
  3. CenterEyeAnchorカメラを選択します。こうすると、常に左目と右目のポーズの平均になります。
    Camera selection
このコンポーネントは次のようになっているはずです。
Camera selected

キューブのサイズを変更してアプリを実行する

キューブは、左コントローラーに「取り付け」ているとユーザーのヘッドポーズに近づきすぎるため、キューブのサイズを少し縮小すると良いでしょう。
  1. [Hierarchy (階層)]タブでCube GameObjectをまだ選択していない場合は選択し、[Inspector (インスペクター)]にフォーカスします。
  2. サイズを[0.2, 0.2, 0.2]に変更します。
    Change cube size
  3. プロジェクトを保存して、[File (ファイル)] > [Build And Run (ビルドして実行)]をクリックし、ヘッドセットを装着してください。
ヘッドセットでアプリを使用している間に、頭をあらゆる方向に動かして、右コントローラーのインデックストリガー、左コントローラーのハンドトリガー、右コントローラーのサムスティック(左右に)、Aボタン(右コントローラー)を押してみてください。

参考スクリプト

以下は、ControllerScript.csのコード全文です。今後の参考にしてください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ControllerScript : MonoBehaviour
{
    public Camera sceneCamera;
    private Vector3 targetPosition;
    private Quaternion targetRotation;
    private float step;

    // Start is called before the first frame update
    void Start()
    {
        // Set initial cube's position in front of user
        transform.position = sceneCamera.transform.position + sceneCamera.transform.forward * 3.0f;
    }

    // Update is called once per frame
    void Update()
    {
        // Define step value for animation
        step = 5.0f * Time.deltaTime;


        // While user holds the right index trigger, center the cube and turn it to face user
        if (OVRInput.Get(OVRInput.RawButton.RIndexTrigger)) centerCube();

        // While thumbstick of right controller is currently pressed to the left
        // rotate cube to the left
        if (OVRInput.Get(OVRInput.RawButton.RThumbstickLeft)) transform.Rotate(0, 5.0f * step, 0);

        // While thumbstick of right controller is currently pressed to the right
        // rotate cube to the right
        if (OVRInput.Get(OVRInput.RawButton.RThumbstickRight)) transform.Rotate(0, -5.0f * step, 0);

        // If user has just released Button A of right controller in this frame
        if (OVRInput.GetUp(OVRInput.Button.One))
        {
            // Play short haptic on right controller
            OVRInput.SetControllerVibration(1, 1, OVRInput.Controller.RTouch);
        }

        // While user holds the left hand trigger
        if (OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger) > 0.0f)
        {
            // Assign left controller's position and rotation to cube
            transform.position = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch);
            transform.rotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch);
        }
    }

    void centerCube()
    // Places cube smoothly at the center of the user's viewport and rotates it to face the camera
    {
        targetPosition = sceneCamera.transform.position + sceneCamera.transform.forward * 3.0f;
        targetRotation = Quaternion.LookRotation(transform.position - sceneCamera.transform.position);

        transform.position = Vector3.Lerp(transform.position, targetPosition, step);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, step);
    }
}

詳しくはこちら

この機能の使用を開始する方法について理解できたら、次のガイドに進みましょう。

デザインガイドライン

  • 入力モダリティ: さまざまな入力モダリティについて学びます。
  • ヘッド: ヘッド入力を使用するための設計とUXのベストプラクティスについて学びます。
  • : 手を使用するための設計とUXのベストプラクティスについて学びます。
  • コントローラー: コントローラーを使用するための設計とUXのベストプラクティスについて学びます。
  • 音声: 音声を使用するための設計とUXのベストプラクティスについて学びます。
  • 周辺機器: 周辺機器を使うための設計とUXのベストプラクティスについて学びます。
ナビゲーションロゴ
日本語
© 2026 Meta