unity-xr について
VR、MR、AR アプリを開発する Unity 6 開発者向けの XR ガイドです。プラットフォーム設定、インタラクション、移動、デバイス入力を含む Unity の XR 構成を解説します。
主な機能
- 01OpenXR の設定とプラットフォーム検証
- 02VR・AR インタラクションコンポーネント
- 03移動プロバイダーと変換処理
- 04AR Foundation のサブシステム
- 05手・コントローラー・視線入力
- 06Editor でのインタラクションテスト
活用シーン
- 01対象ハードウェア向けの OpenXR 設定
- 02オブジェクトの把持とテレポートの実装
- 03AR トラッキングとジェスチャーの追加
- 04XR ハードウェアなしでの操作テスト
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-xrインストール後、Claude Code で/unity-xrを入力して読み込まれたか確認します。
同梱ファイルreferences/xr-toolkit.md
詳細
Unity 6 XR 開発ガイド
出典:Unity 6.3 LTS ドキュメント(6000.3)
XR アーキテクチャの概要
Unity では、XR は次の 3 種類のアプリケーションを含むものと定義されています。
- 仮想現実(VR) -- ユーザーを取り囲む独立した環境をアプリケーションでシミュレートします
- 複合現実(MR) -- 仮想環境と現実世界の環境を組み合わせ、インタラクションを実現します
- 拡張現実(AR) -- 現実世界の視界にコンテンツを重ねて表示します
Unity 6 の XR スタックは、次の要素で構成されます。
- XR プラグイン管理 -- プラットフォームの XR SDK を検出して読み込みます
- OpenXR プラグイン -- Khronos によるオープンかつロイヤリティフリーな、クロスプラットフォーム XR の標準規格です
- XR Interaction Toolkit(XRI) -- 高レベルのコンポーネントベースのインタラクションシステムです
- AR Foundation -- プロバイダープラグインアーキテクチャを備えたクロスプラットフォーム AR フレームワークです
- Input System -- OpenXR と XRI が必要とするアクションベースの入力システムです
XR プラグイン管理
Edit > Project Settings > XR Plug-in Management から設定します。
- プラットフォームごとに OpenXR と必要な Feature Groups を有効にします
- OpenXR の Features タブで Interaction Profiles(コントローラーマッピング)を選択します
- ビルド時の互換性チェックを行うには、Project Validation を実行します
- アクティブなランタイムが対象ハードウェアと一致していることを確認します
サポートされるランタイムとプラットフォーム
| ランタイム | 対象 | グラフィックス |
|---|---|---|
| Windows Mixed Reality | Win64 | DX11 |
| Oculus PC + Link | Win64 | DX11 |
| Meta Quest | Android arm64 | Vulkan |
| Magic Leap 2 | Android x64 | Vulkan |
| SteamVR | Win64 | DX11 |
OpenXR インタラクションプロファイル
- Eye Gaze Interaction
- HTC Vive Controller
- Khronos Simple Controller
- Microsoft Motion Controller
- Oculus Touch Controller
- Valve Index Controller
OpenXR スクリプティング API
// Iterate all OpenXR features
var features = OpenXRSettings.Instance.GetFeatures();
foreach (var feature in features)
{
Debug.Log($"Feature: {feature.name}, Enabled: {feature.enabled}");
}
// Get a specific feature by type
var feature = OpenXRSettings.Instance.GetFeature<MockRuntime>();
if (feature != null)
{
Debug.Log($"MockRuntime Enabled: {feature.enabled}");
}
// Iterate feature groups (Editor only)
var featureSets = OpenXRFeatureSetManager.FeatureSetsForBuildTarget(
BuildTargetGroup.Standalone
);
foreach (var featureSet in featureSets)
{
Debug.Log($"Feature Set ID: {featureSet.featureSetId}");
}
XR Interaction Toolkit
パッケージ: com.unity.xr.interaction.toolkit(Unity 6000.3 用 v3.3.1)
VR と AR 向けの高レベルなコンポーネントベースのインタラクションシステムです。基盤となる要素は 3 つあります。
- インタラクター -- ユーザー入力を処理し、インタラクションを開始します
- インタラクタブル -- ユーザーが操作できるオブジェクトを定義します
- Interaction Manager -- インタラクターとインタラクタブルの連携を調整します
インタラクションの状態
| 状態 | 説明 |
|---|---|
| Hover | インタラクタブルが有効な対象であり、操作の意図を示します |
| Select | ユーザー入力(ボタン/トリガー)によってアクティブなインタラクション(つかむ)が実行されます |
| Focus | 選択後、別のインタラクタブルが選択されるまで状態が維持されます |
| Activate | 追加のコントロールに割り当てられた、コンテキストに応じた副次的なアクションです |
更新ループ
- インタラクターから有効な対象リストを取得します
- 既存のホバー/フォーカス/選択状態を検証します
- 無効な状態を終了します(
OnSelectExiting、OnHoverExiting、OnFocusExiting) - 新しい状態に入ります(
OnSelectEntering、OnHoverEntering、OnFocusEntering)
処理と状態変更のどちらにおいても、インタラクタブルより先にインタラクターに通知されます。
インタラクターの種類
| コンポーネント | 目的 |
|---|---|
| XR Direct Interactor | 近距離での(タッチ/つかむ)インタラクション |
| XR Ray Interactor | レイを使った遠距離インタラクション |
| XR Poke Interactor | 突く/触れるインタラクション |
| Near-Far Interactor | 近接/遠距離のハイブリッドインタラクション |
| XR Gaze Interactor | 視線によるインタラクション |
| XR Socket Interactor | スナップポイントを使ったインタラクション |
| Climb Teleport Interactor | 登る移動 |
インタラクタブルの種類
| コンポーネント | 目的 |
|---|---|
| XR Grab Interactable | オブジェクトをつかんで操作します |
| XR Simple Interactable | 基本的なインタラクションイベント |
| Climb Interactable | 登ることができる表面 |
| Teleportation Anchor | 固定されたテレポート先 |
| Teleportation Area | エリアベースのテレポート対象 |
| Teleportation Multi-Anchor Volume | 複数のアンカーを持つボリューム |
XR Grab Interactable の移動タイプ
- 瞬間移動 -- 毎フレーム、Transform の位置/回転を設定します。レイテンシーが最も低い一方で、コライダーをすり抜けることがあります。
- キネマティック -- FixedUpdate 中にキネマティック Rigidbody を更新します。物理演算とビジュアルを同期させます。
- 速度トラッキング -- Rigidbody の速度/角速度を設定します。衝突の貫通を防ぎますが、遅延が発生する場合があります。
インタラクションの強度
インタラクターとインタラクタブルは、正規化された [0.0, 1.0] のアナログ選択強度を報告します。これは状態変化後に処理されます。
インタラクショングループ
グループには、優先度順に並べられた複数のメンバーインタラクターが含まれ、グループ内で一度にインタラクションできるインタラクターは1つだけです。グループのネストにも対応しています。
API の詳細については、skills/unity-xr/references/xr-toolkit.md を参照してください。
ロコモーションシステム
ロコモーションプロバイダー
| プロバイダー | 説明 |
|---|---|
| テレポーテーションプロバイダー | ポイントしてテレポートする移動 |
| スナップターンプロバイダー | 固定角度でユーザーを回転 |
| 連続ターンプロバイダー | 時間をかけて滑らかに回転 |
| 連続移動プロバイダー | 時間をかけて滑らかに移動 |
| グラブ移動プロバイダー | コントローラーの移動と逆方向にユーザーを移動 |
| 両手グラブ移動プロバイダー | 2つのコントローラーによる移動、回転、スケーリング |
| クライムプロバイダー | クライムインタラクタブルを選択している間の移動 |
| 重力プロバイダー | 接地状態の検出を伴う重力効果 |
アーキテクチャ
- ロコモーションメディエーター -- 変換リクエストを管理します。状態は Idle、Preparing、Moving、Ended です。
- XR ボディトランスフォーマー -- 優先度に基づいて、各 Update で適用する変換をキューに登録します。
- XR ムーバブルボディ -- XR Origin を、ボディを基準とした変換でラップします。
変換は優先度の昇順で順次適用されます。同じ優先度の変換は、キューの順序で適用されます。
AR Foundation
パッケージ: com.unity.xr.arfoundation(Unity 6000.3 向け v6.3.3)
AR Foundation は、2パッケージ構成のアーキテクチャを採用しています。
- ベースパッケージ -- AR 機能のインターフェースを提供します(単体では機能しません)。
- プロバイダープラグイン -- プラットフォーム固有の実装を提供します。
対応プラットフォーム
| プラットフォーム | プロバイダープラグイン |
|---|---|
| Android | Google ARCore XR Plug-in |
| iOS | Apple ARKit XR Plug-in |
| visionOS | Apple visionOS XR Plug-in |
| HoloLens 2 | OpenXR Plug-in |
| Meta Quest | Unity OpenXR: Meta |
| Android XR | Unity OpenXR: Android XR |
機能サブシステム
| 機能 | マネージャーコンポーネント |
|---|---|
| セッション管理 | ARSession |
| デバイストラッキング | ARTrackedPoseDriver |
| カメラ | ARCameraManager |
| 平面検出 | ARPlaneManager |
| 画像トラッキング | ARTrackedImageManager |
| 顔トラッキング | ARFaceManager |
| ボディトラッキング | ARHumanBodyManager |
| オブジェクトトラッキング | ARTrackedObjectManager |
| ポイントクラウド | ARPointCloudManager |
| レイキャスティング | ARRaycastManager |
| アンカー | ARAnchorManager |
| メッシュ生成 | ARMeshManager |
| 環境プローブ | AREnvironmentProbeManager |
| オクルージョン | AROcclusionManager |
| バウンディングボックス検出 | ARBoundingBoxManager |
| 参加者 | ARParticipantManager |
AR ジェスチャーインタラクション(XRI)
- TouchscreenGestureInputController -- 画面のタッチをジェスチャーイベントにマッピングします。
- ARTransformer -- 配置、選択、移動、回転、スケーリングのジェスチャーを処理します。
- スクリーンスペース入力コンポーネントは XRRayInteractor に入力を渡します。
ハンドトラッキング
ハンドトラッキングデバイスは、HandTracking 特性と CommonUsages.HandData 機能を公開します。
Hand handData;
if (device.TryGetFeatureValue(CommonUsages.handData, out handData))
{
// Get wrist bone
Bone rootBone;
if (handData.TryGetRootBone(out rootBone))
{
Vector3 wristPosition;
rootBone.TryGetPosition(out wristPosition);
}
// Get finger bones (up to 21 bones per hand)
List<Bone> fingerBones = new List<Bone>();
if (handData.TryGetFingerBones(HandFinger.Index, fingerBones))
{
foreach (Bone bone in fingerBones)
{
Vector3 bonePosition;
bone.TryGetPosition(out bonePosition);
}
}
}
各ボーンには、位置、向き、親/子への参照が含まれます。
コントローラーとハプティクス
入力デバイスへのアクセス
using UnityEngine.XR;
// Get devices by role
var devices = new List<InputDevice>();
InputDevices.GetDevicesWithRole(InputDeviceRole.RightHanded, devices);
if (devices.Count > 0)
{
var device = devices[0];
// Read trigger button
bool triggerPressed;
if (device.TryGetFeatureValue(CommonUsages.triggerButton,
out triggerPressed) && triggerPressed)
{
// Handle trigger press
}
// Read joystick axis
Vector2 axis;
if (device.TryGetFeatureValue(CommonUsages.primary2DAxis, out axis))
{
// Use axis.x, axis.y
}
}
一般的な入力の用途
| 用途 | 型 | 説明 |
|---|---|---|
primary2DAxis | Vector2 | サムスティック/タッチパッド |
trigger | float | トリガー軸(0~1) |
grip | float | グリップ軸(0~1) |
triggerButton | bool | トリガーが押されている |
gripButton | bool | グリップが押されている |
primaryButton | bool | A/X ボタン |
secondaryButton | bool | B/Y ボタン |
menuButton | bool | メニューボタン |
userPresence | bool | ユーザーがヘッドセットを装着している |
触覚フィードバック
HapticCapabilities capabilities;
if (device.TryGetHapticCapabilities(out capabilities))
{
if (capabilities.supportsImpulse)
{
uint channel = 0;
float amplitude = 0.5f; // 0-1
float duration = 1.0f; // seconds
device.SendHapticImpulse(channel, amplitude, duration);
}
}
アイトラッキング
Eyes eyeData;
if (device.TryGetFeatureValue(CommonUsages.eyesData, out eyeData))
{
// Access left/right eye positions, gaze direction, blink amounts
}
デバイスのライフサイクル
// Subscribe to connection events
InputDevices.deviceConnected += OnDeviceConnected;
InputDevices.deviceDisconnected += OnDeviceDisconnected;
// Always validate before use
if (device.isValid)
{
// Safe to read features
}
トラッキングの原点
var subsystems = new List<XRInputSubsystem>();
SubsystemManager.GetInstances<XRInputSubsystem>(subsystems);
if (subsystems.Count > 0)
{
subsystems[0].TrySetTrackingOriginMode(TrackingOriginModeFlags.Floor);
// Get play area boundary
List<Vector3> boundaryPoints = new List<Vector3>();
if (subsystems[0].TryGetBoundaryPoints(boundaryPoints))
{
// Points are floor-level, clockwise-ordered
}
}
一般的なパターン
基本的な XR リグのセットアップ
- シーンに XR Origin を追加します(カメラのオフセットとボディトラッキングを提供します)
- XR Interaction Manager を追加します(単一のインスタンスですべてのインタラクションを調整します)
- カメラとコントローラーに Tracked Pose Driver を追加します
- コントローラーの GameObject に Interactors を追加します
- インタラクティブなオブジェクトに Interactables を追加します
オブジェクトをつかむパターン
// On the grabbable object:
// 1. Add Rigidbody
// 2. Add Collider
// 3. Add XR Grab Interactable component
// Configure Movement Type based on needs:
// - Instantaneous: lowest latency, no physics
// - Kinematic: physics-synced, moderate latency
// - Velocity Tracking: full physics, potential lag
推奨されるグラブ階層
Grab Interactable (Rigidbody, XRGrabInteractable)
├── Visuals (MeshFilter, MeshRenderer)
├── Collider (BoxCollider, MeshCollider)
└── Visual Feedback (Affordance providers)
XR Interaction Simulator
XR Interaction Simulator コンポーネントを使用すると、物理デバイスなしでエディター内のインタラクションをテストできます。
避けるべきパターン
- Interaction Manager がない -- すべての Interactor と Interactable には、共有の Interaction Manager が必要です。設定を忘れると、何も表示されずに失敗します。
- OpenXR でレガシー Input Manager を使用する -- OpenXR には新しい Input System パッケージが必要です。レガシーな
Input.GetAxis()は動作しません。 - デバイスの検証を省略する -- 機能を読み取る前に、必ず
InputDevice.isValidを確認してください。デバイスはいつでも切断される可能性があります。 - ソケットの Attach Ease In Time を無視する -- Socket Interactor のビジュアルにちらつきが発生します。軽減するには、Attach Ease In Time を少なくとも 0.15 に設定してください。
- XR プロバイダーでマウス/ワールド空間 UI を使用する -- XR Plug-in Providers を有効にすると、標準のマウスとワールド空間 UI が機能しなくなります。代わりに XR UI Input Module を使用してください。
- コンピュートシェーダーのサポートを確認しない -- コンピュートシェーダーに対応していないプラットフォームでは、GPU ベースの機能が何も表示されずに失敗する可能性があります。
SystemInfo.supportsComputeShadersを確認してください。 - ビネットなしでテレポートする -- Tunneling Vignette Controller を使用せずに瞬時にテレポートすると、乗り物酔いが発生します。
- UI Toolkit で Poke Interactor を使用する -- 既知の制限事項です。代わりに、Tracked Device Graphic Raycaster を使用した Canvas ベースの UI を使用してください。
主要 API クイックリファレンス
| クラス | 名前空間 | 目的 |
|---|---|---|
XROrigin | Unity.XR.CoreUtils | カメラリグとトラッキング空間 |
XRInteractionManager | UnityEngine.XR.Interaction.Toolkit | インタラクションの調整 |
XRBaseInteractor | UnityEngine.XR.Interaction.Toolkit | Interactor の基底クラス |
XRBaseInteractable | UnityEngine.XR.Interaction.Toolkit | Interactable の基底クラス |
XRGrabInteractable | UnityEngine.XR.Interaction.Toolkit | つかめるオブジェクト |
InputDevice | UnityEngine.XR | 物理 XR デバイス |
InputDevices | UnityEngine.XR | デバイスの検出 |
CommonUsages | UnityEngine.XR | 標準入力機能名 |
OpenXRSettings | UnityEngine.XR.OpenXR | OpenXR の設定 |
ARSession | UnityEngine.XR.ARFoundation | AR セッションの管理 |
ARPlaneManager | UnityEngine.XR.ARFoundation | 平面の検出 |
ARAnchorManager | UnityEngine.XR.ARFoundation | 空間アンカー |
関連スキル
unity-input-- Input System パッケージ、アクションマップ、バインディングunity-graphics-- レンダリングパイプライン、XR 向けのシェーダーに関する考慮事項