跨平台空间交互层(Quest + Vision Pro)
把 Quest 和 Vision Pro 的 XR 交互归到一条统一链路——底层 OpenXR,设备层分叉(Meta XR SDK vs PolySpatial/Metal),但上面的 XR Interaction Toolkit 保持一致。配套一个可在 Unity 6 打开、构建到设备的真实 Unity 工程(OpenXR + XRI)。
分层思路来自 SpatialXR(广州虚境起源)的 Unity 空间计算视频课程(Meta Quest / Apple Vision Pro 两套)。课程是纯视频(.sz 即改名 MP4、无字幕)+ 加密 RAR 素材,只有 3 份 PDF 可读、给出真实 SDK / 组件词汇——所以下面的交互流程与分层架构是从文档梳理的。在此之上,另配了一个可运行的 Unity 工程(OpenXR + XRI,Quest-first,含 Vision Pro / PolySpatial 路径说明),见下方「配套 Unity 工程」。
核心判断:设备层会分叉,交互层不该分叉
要同时做 Quest 和 Vision Pro,最容易踩的坑是为每个平台各写一套交互代码。课程文档给出的更干净的做法是分层:
- 基座:OpenXR —— 跨厂商标准,可移植性的地基
- 设备 / 渲染层(分叉点):
- Quest 走 Meta XR SDK(课程涵盖 v72 → v76+,层叠在 OpenXR 之上)
- Vision Pro 走 Unity PolySpatial(RealityKit) 或 Metal —— 这是 visionOS 的两种渲染模式
- 交互层:XR Interaction Toolkit(XRI) —— 保持一致,抓取 / 射线 / 戳 UI 这些交互不随平台改写
┌─────────────────────────────┐
应用 / 交互逻辑 │ XR Interaction Toolkit (XRI) │ ← 跨平台保持一致
└─────────────────────────────┘
▲ ▲
┌─────────────────┘ └─────────────────┐
设备/渲染 │ Meta XR SDK (v72→v76+) │ │ PolySpatial (RealityKit) · Metal │ ← 分叉点
└────────────────────────┘ └──────────────────────────────────┘
▲ ▲
基座 └──────── OpenXR ────────┘ ← 可移植性地基
真实 XRI 组件(来自课程 PDF)
| 类别 | 组件 | 说明 |
|---|---|---|
| 可抓物体 | XRGrabInteractable | Movement Type:Instantaneous / Kinematic / Velocity-Tracking;Throw On Detach 控制松手投掷 |
| 双手变换 | XRGeneralGrabTransformer | 双手抓同一物体做缩放 / 旋转 |
| Interactor | XRSpatialPointerInteractor | PolySpatial 2.0.4 之前叫 XRTouchSpaceInteractor |
| Interactor | Near-Far Interactor / XR Poke Interactor | 近场戳按 / 远场射线 |
| visionOS 反馈 | VisionOSHoverEffect / VisionOSGroundingShadow | 悬停高亮 / 接地阴影 |
| 渲染容器 | Volume Camera | PolySpatial 的体积相机 |
| World-Space UI | Tracked Device Graphic Raycaster + InputSystemUIInputModule | 让 3D 空间里的 UI 能被射线 / 戳交互 |
XRGrabInteractable 的 Movement Type 是个有意思的对照:Kinematic 让物体稳稳跟手(适合精密操作);Velocity-Tracking 跟踪手的速度,配 Throw On Detach 就能把物体"扔"出去。这两个模式在 Demo 里随平台切换演示。
手部追踪链路
课程文档化的手追踪是一条递进链:
手骨架(26 关节) → 关节渲染 → 驱动虚拟手 → 把物体绑到关节 → 手势识别
│
拇指 + 食指捏合 → 视为一次 button
捏合手势被归一化成"按钮"语义后,就能复用 XRI 的 select 事件,不必为手势单独写一套输入。
一次完整交互(Demo 复演的流程)
原始手关节
└─> 捏合检测(thumb + index pinch)
└─> 射线命中远处的 XRGrabInteractable
└─> 抓取
├─ Quest:Kinematic(稳跟手)
└─ Vision Pro:Velocity-Tracking(Throw On Detach 可投掷)
└─> World-Space UI:XR Poke Interactor 戳按钮
(经 Tracked Device Graphic Raycaster + InputSystemUIInputModule)
互动 Demo 把这条链路做成可点的复演,并带一个 Quest ⟷ Vision Pro 切换:切换时只有"设备 / 渲染层"那一格换 SDK 名,"OpenXR"和"XRI"两格保持绿色(一致)——直观展示分叉点在哪、可移植性来自哪。
配套 Unity 工程(可运行)
网页 Demo 是交互流程的可视化复演;真正可跑的是一个独立的 Unity 6 工程:spatial-xr-interaction/。
- 代码即交互:
SpatialInteractionBootstrap运行时生成两个可抓方块(Kinematic vs Velocity-Tracking)+ 一个 World-Space 戳按钮;HandPinchDetector用 XR Hands 做拇指↔食指捏合;PlatformLayer检测 Quest / Vision Pro / 编辑器并打日志,标出「分叉点」 - 跨平台靠分层:OpenXR + XRI 的 Starter Assets 提供 XR Origin 与 interactor,工程代码只写「要交互的内容」,不为平台改写交互
- 怎么跑:Unity 6 打开 → 导入 XRI Starter Assets 样例 → XR Plug-in Management 开 OpenXR + Meta Quest feature group → 装上 bootstrap 脚本 → 编辑器内用 XR Device Simulator 试玩,或 Build And Run 到 Quest(Android);Vision Pro 走 PolySpatial(README 有 opt-in 步骤)
诚实说明:工程代码基于公开 Unity XR 文档 + 课程文档化的组件词汇编写(课程纯视频、无源码),且尚未在本机 Unity 里编译过(本机只装了 Unity Hub、未装 Editor)——以打开后为准,XRI 小版本可能需个别 API 名微调。README 里都写清楚了。
价值点
- 跨平台 XR 架构判断力:知道哪些该收敛(OpenXR + XRI),哪些必然分叉(Meta XR SDK vs PolySpatial/Metal)
- OpenXR 可移植性:以标准为地基而不是绑死单一厂商
- Apple 空间计算深度:理解 visionOS 的 PolySpatial(RealityKit)vs Metal 两种渲染模式之分,以及
Volume Camera/VisionOSHoverEffect/VisionOSGroundingShadow这些 Apple 专属反馈组件 - 从文档到能跑的工程:把视频课文档化的架构落成一个真实可构建的 Unity 6 工程(OpenXR + XRI),而不是停在 PPT 复述
Demo 真实材料对应
网页互动 Demo 复演课程文档里的 XRI 交互链(手骨架 → 捏合 → 射线 → 抓取 → 戳 World-Space UI),带 Quest ⟷ Vision Pro 切换。组件名(XRGrabInteractable / XR Poke Interactor / PolySpatial / Volume Camera 等)取自课程 PDF。真正可运行的是配套的 Unity 6 工程(spatial-xr-interaction/,OpenXR + XRI)——代码基于公开 Unity XR 文档 + 课程组件词汇编写(课程纯视频无源码),尚未在本机编译,以打开 Unity 后为准。