ハイライト
Unity は完全な XR エコシステムを visionOS に持ち込み、開発者は慣れたワークフローで VR プロジェクトを移植できます。核心パスは: visionOS ビルドターゲットを選択、XR Plug-in を有効化、URP でフォベーテッドレンダリングとシングルパスインスタンスレンダリングを使用、XR Interaction Toolkit または Unity Hands Package でコントローラ入力をジェスチャ入力に適応させることです。
主要内容
完全没入型体験への2つのパス
(00:33) Unity は visionOS 上で2種類の没入型体験をサポートします:
- 完全没入型: ユーザーの周囲環境を置き換え、別の世界に送ります。Compositor Services と Metal レンダリングを使用します
- 混合没入型: コンテンツを現実世界のパススルーとブレンドします。Shared Space で他のアプリと共存します
このセッションは完全没入型パスに焦点を当てます。もう一方のパスは「Create immersive Unity apps」を参照してください。
ビルドと実行のワークフロー
(02:25) Unity は visionOS 向けの完全なビルドサポートを提供します:
- visionOS ビルドターゲットを選択
- XR Plug-in を有効化
- ネイティブプラグインを再コンパイル(.mm ソースファイルは変更不要)
- Unity から Xcode プロジェクトを生成
- Xcode でデバイスまたはシミュレータにビルド&実行
このフローは iOS、Mac、Apple TV ターゲットと同じで、開発者は既に慣れています。
グラフィックスパイプラインの重要な設定
Universal Render Pipeline(URP)
(03:29) URP は visionOS 独自のフォベーテッドレンダリングをサポートするため推奨されます。
フォベーテッドレンダリングはレンズ中心部により多くのピクセル密度を集中し、周辺部の詳細を減らします。人間の目は中心領域により敏感なため、この技術はレンダリング負荷を増やさずに視覚品質を向上させます。
URP では静的フォベーテッドレンダリングがパイプライン全体に自動適用され、ポストプロセス、カメラスタッキング、HDR などと互換性があります。カスタムレンダーパスは Unity 2022 の新 API でこの技術を活用できます。
Single-Pass Instanced Rendering
(04:40) シングルパスインスタンスレンダリングは Metal API をサポートし、デフォルトで有効です。エンジンは両眼に対して1回だけドローコールを送信し、カリング、シャドウなどのレンダリングパイプラインオーバーヘッドを削減し、ステレオレンダリングの CPU 負荷を下げます。
アプリが他の VR プラットフォームでシングルパスインスタンスレンダリングを正しく使用している場合、シェーダマクロにより visionOS でも動作します。
深度バッファ
(05:14) システムコンポジターは深度バッファで再投影を行います。各ピクセルは正しい深度値を書き込む必要があり、深度情報が欠けた領域は誤った色で表示されます。
スカイボックスは通常ユーザーから無限遠にあり、reverse Z で深度 0 を書き込むため、デバイスで正しく表示するには修正が必要です。Unity はすべての組み込みシェーダの深度書き込みを修正しましたが、カスタムエフェクト(カスタムスカイボックス、水面エフェクト、透明エフェクト)は各ピクセルに深度値があることを確認する必要があります。
インタラクションシステム: コントローラから手へ
visionOS のインタラクションは手と目に依存します。Unity は適応のための3層のツールを提供します:
XR Interaction Toolkit(XRI)
(06:09) XRI は高レベルのインタラクションシステムで、入力タイプを抽象化し、インタラクションコードをクロスプラットフォームで動作させます。3D と UI オブジェクトをサポートし、ホバー、グラブ、選択などの一般的なインタラクションに応答します。
コアコンポーネント:
- Interactable: 入力を受け取るシーン内オブジェクト。3つの組み込みタイプ: Simple(インタラクションイベントを受信)、Grab(選択後にインタラクターに追従)、Teleport(テレポート領域/ポイントを定義)
- Interactor: Interactable とのインタラクション方法。Direct Interactor(タッチで選択)、Ray Interactor(遠距離レイ選択、曲線/直線)、Socket Interactor(オブジェクトを受け入れる領域を定義)、Poke Interactor(方向フィルタ付きポークインタラクション)、Gaze Interactor(視線インタラクション、コライダーを自動拡大)
- Interaction Manager: Interactor と Interactable 間のインタラクション状態を調整
- XR Controller: 入力アクションを Interactor に渡す
Unity Input System
(11:35) システムジェスチャ入力を直接使用します。ピンチジェスチャは位置と回転を含む値として渡されます。視線方向とピンチジェスチャは同じフレームで渡されます。
Unity Hands Package
(12:12) 低レベルの手関節データをクロスプラットフォームで一貫してアクセスできます。ジェスチャ検出(親指を立てる、人差し指を伸ばす)やカスタムハンドメッシュの駆動に使用できます。
詳細
人差し指が伸びているかを検出
(12:46)
static bool IsIndexExtended(XRHand hand)
{
if (!(hand.GetJoint(XRHandJointID.Wrist).TryGetPose(out var wristPose) &&
hand.GetJoint(XRHandJointID.IndexTip).TryGetPose(out var tipPose) &&
hand.GetJoint(XRHandJointID.IndexIntermediate).TryGetPose(out var intermediatePose)))
{
return false;
}
var wristToTip = tipPose.position - wristPose.position;
var wristToIntermediate = intermediatePose.position - wristPose.position;
return wristToTip.sqrMagnitude > wristToIntermediate.sqrMagnitude;
}
キーポイント:
XRHandJointID.Wrist、IndexTip、IndexIntermediateで3つの主要関節を取得しますTryGetPoseで関節ポーズを取得し、false は関節データが無効であることを示します- 手首から指先、手首から中間関節へのベクトルを計算します
- 二乗距離を比較: 指先の距離が中間関節より大きければ人差し指は伸びています
- 他の指にもこのロジックを拡張して基本的なジェスチャ検出を実装できます
OnHandUpdateイベントで左手または右手を渡して呼び出します
XRI Interaction Manager の設定
Interaction Manager は Interactor と Interactable の仲介役です:
// 通常1つの Interaction Manager がすべてのインタラクションを管理
// 異なるシーン/メニュー用に複数の Manager を設定することも可能
// 例: ゲームプレイとメニューで別々の Manager
public InteractionManager gameplayManager;
public InteractionManager menuManager;
void EnterGameplay() {
gameplayManager.enabled = true;
menuManager.enabled = false;
}
void EnterMenu() {
gameplayManager.enabled = false;
menuManager.enabled = true;
}
キーポイント:
- 単一の Interaction Manager で通常は十分です
- 複数の補完的な Manager で特定のインタラクションセットを有効/無効にできます
- 例: ゲームシーンとメニューで異なる Interactable セットを使用
カスタムハンドメッシュ
RecRoom は生の手関節データでスタイライズされた手モデルを駆動します:
// すべての関節位置を取得
foreach (XRHandJointID jointID in Enum.GetValues(typeof(XRHandJointID)))
{
if (hand.GetJoint(jointID).TryGetPose(out var pose))
{
// 関節位置をカスタムボーンにマッピング
customHandMesh.SetJointPosition(jointID, pose.position);
customHandMesh.SetJointRotation(jointID, pose.rotation);
}
}
キーポイント:
- Unity Hands Package はクロスプラットフォームで一貫した関節データを提供します
- 任意のカスタムハンドモデルを駆動できます
- ハンドの視覚スタイルをゲーム全体のスタイルと統一できます
- 他プレイヤーの手モデルを表示して没入感を高めることもできます
深度バッファチェックリスト
| エフェクトタイプ | 深度書き込み要件 | 注意事項 |
|---|---|---|
| 不透明オブジェクト | 書き込み必須 | Unity 組み込みシェーダは修正済み |
| スカイボックス | 修正が必要 | 無限遠オブジェクト、reverse Z で 0 を書き込み |
| 透明/水面 | 値の存在を確認 | カスタムエフェクトは要確認 |
| パーティクルシステム | 設定を確認 | 一部パーティクルは深度書き込みをスキップする場合あり |
| ポストプロセス | 影響なし | 深度テスト後に実行 |
重要ポイント
1. 既存の Unity VR ゲームを visionOS に移植
- やること: SteamVR や Oculus の Unity ゲームを visionOS に持ち込む
- 価値がある理由: ワークフローはほぼ変わりません: ターゲット選択、XR Plug-in 有効化、Xcode プロジェクト生成。URP は自動的にフォベーテッドレンダリングを取得し、シングルパスインスタンスレンダリングで CPU オーバーヘッドを削減します
- 始め方: Unity 2022 にアップグレード、URP に切り替え、カスタムシェーダの深度書き込みを確認、コントローラ固有コードを XRI に置き換え、シミュレータで反復テストします
2. ジェスチャインタラクション向けの新しいゲームメカニクスを設計
- やること: ジェスチャをネイティブサポートする VR パズルまたはアクションゲームを設計する
- 価値がある理由: visionOS のハンドトラッキングは高精度で低レイテンシです。XRI の Poke Interactor と Grab Interactor で自然なジェスチャが直接ゲーム入力になります。コントローラ不要で参入障壁が低くなります
- 始め方: XRI の Grab Interactor でオブジェクトグラブ、Poke Interactor でボタン押下、Unity Hands Package で特定ジェスチャを検出して特殊能力をトリガーします
3. 没入型バーチャルトレーニングシミュレータを構築
- やること: 医療、産業、安全トレーニング向けの VR シミュレーションアプリを開発する
- 価値がある理由: 完全没入型空間でユーザーはトレーニングコンテンツに集中できます。ハンドトラッキングで仮想ツール操作が現実に近い体験になります。フォベーテッドレンダリングで重要な詳細が鮮明に保たれます
- 始め方: Full Immersive スタイルの Immersive Space を作成し、XRI の Socket Interactor でツールの収納、Ray Interactor で遠距離選択を実装します
4. ソーシャル VR 空間を作成
- やること: マルチプレイヤーの仮想集会またはコラボレーション空間を構築する
- 価値がある理由: RecRoom がこの道の実現可能性を証明しました。Unity のネットワーク機能を再利用でき、XRI のインタラクションシステムが入力タイプを抽象化し、クロスプラットフォームプレイヤーが一緒にインタラクションできます
- 始め方: 既存の Unity マルチプレイヤーネットワークコードを再利用し、カスタムハンドメッシュでプレイヤーの手を表示し、Gaze Interactor で視線選択のヒットを容易にします
関連セッション
- Create immersive Unity apps — visionOS Shared Space での没入型 Unity アプリ開発
- Build great games for spatial computing — 空間コンピューティングゲーム開発技術の概要
- Discover Metal for immersive apps — Metal による visionOS 完全没入型体験の直接レンダリング
コメント
GitHub Issues · utterances