关于 unity-xr
面向 Unity 6 VR、MR 和 AR 开发者的 XR 开发指南,涵盖平台配置、交互、移动和设备输入,并梳理 Unity XR 工具栈的关键组件。
主要功能
- 01OpenXR 配置与平台验证
- 02VR 和 AR 交互组件
- 03移动提供程序与变换
- 04AR Foundation 子系统
- 05手部、控制器与眼动输入
- 06在 Editor 中测试交互
适用场景
- 01为目标硬件配置 OpenXR
- 02实现物体抓取与传送
- 03添加 AR 跟踪和手势
- 04不连接 XR 硬件测试交互
安装
复制下面的命令,在终端中运行。
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 定义为涵盖三种应用类型:
- 虚拟现实(VR) -- 应用在用户周围模拟一个独立的环境
- 混合现实(MR) -- 将虚拟环境与真实世界场景结合,以实现交互
- 增强现实(AR) -- 应用在真实世界视图上叠加内容
Unity 6 中的 XR 技术栈包含:
- XR Plug-in Management -- 发现并加载平台 XR SDK
- OpenXR Plugin -- Khronos 推出的开放、免版税跨平台 XR 标准
- XR Interaction Toolkit(XRI) -- 基于组件的高级交互系统
- AR Foundation -- 采用提供程序插件架构的跨平台 AR 框架
- Input System -- OpenXR 和 XRI 所需的基于操作的输入系统
XR Plug-in Management
通过 Edit > Project Settings > XR Plug-in Management 配置。
- 按平台启用 OpenXR 和所需的 Feature Groups
- 在 OpenXR > Features 选项卡中选择 Interaction Profiles(控制器映射)
- 运行 Project Validation,检查构建时的兼容性
- 确认活动运行时与目标硬件匹配
支持的运行时和平台
| 运行时 | 目标平台 | 图形 API |
|---|---|---|
| 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 的基于组件的高级交互系统。包含三个基础元素:
- 交互器 -- 处理用户输入并发起交互
- 可交互对象 -- 定义用户可以与之交互的对象
- 交互管理器 -- 协调交互器和可交互对象之间的交互
交互状态
| 状态 | 描述 |
|---|---|
| 悬停 | 可交互对象是有效目标;表示交互意图 |
| 选择 | 用户输入(按钮/扳机)触发主动交互(抓取) |
| 焦点 | 选择后持续保持,直到选中另一个可交互对象 |
| 激活 | 映射到其他控制项的次要情境操作 |
更新循环
- 从交互器请求有效目标列表
- 验证现有悬停/焦点/选择状态
- 退出无效状态(
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 抓取可交互对象的移动类型
- Instantaneous —— 每帧设置 Transform 位置/旋转;延迟最低,但可能穿过碰撞体
- Kinematic —— 在 FixedUpdate 期间更新运动学 Rigidbody;使物理状态与视觉效果同步
- Velocity Tracking —— 设置 Rigidbody 速度/角速度;可防止穿透碰撞体,但可能存在延迟
交互强度
交互器和可交互对象会报告归一化的 [0.0, 1.0] 模拟选择强度,并在状态更改后处理。
交互组
组包含多个按优先级排序的成员交互器,并且每次只允许组中的一个交互器进行交互。支持嵌套组。
完整 API 详情请参阅 skills/unity-xr/references/xr-toolkit.md。
移动系统
移动提供程序
| 提供程序 | 描述 |
|---|---|
| Teleportation Provider | 指向并传送 |
| Snap Turn Provider | 按固定角度旋转用户 |
| Continuous Turn Provider | 随时间平滑旋转 |
| Continuous Move Provider | 随时间平滑移动 |
| Grab Move Provider | 使用户沿控制器移动的反方向移动 |
| Two-Handed Grab Move Provider | 双控制器移动、旋转、缩放 |
| Climb Provider | 选择攀爬可交互对象时移动 |
| Gravity Provider | 重力效果及接地状态检测 |
架构
- Locomotion Mediator —— 管理变换请求;状态:Idle、Preparing、Moving、Ended
- XR Body Transformer —— 根据优先级排队并在每次 Update 中应用变换
- XR Movable Body —— 使用身体相对变换封装 XR Origin
变换按优先级升序依次应用;优先级相同时,按队列顺序应用变换。
AR Foundation
Package: com.unity.xr.arfoundation(Unity 6000.3 对应 v6.3.3)
AR Foundation 采用双包架构:
- 基础包 —— 提供 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 Rig 设置
- 在场景中添加 XR Origin(提供相机偏移和身体追踪)
- 添加 XR Interaction Manager(单个实例协调所有交互)
- 在相机和控制器上添加 Tracked Pose Driver
- 将 Interactors 添加到控制器 GameObject
- 将 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 交互模拟器
使用 XR Interaction Simulator 组件,无需实体硬件即可在编辑器中测试交互。
反模式
- 缺少单一 Interaction Manager —— 所有 Interactors 和 Interactables 都需要共享一个 Interaction Manager。忘记添加会导致静默失败。
- 在 OpenXR 中使用旧版 Input Manager —— OpenXR 需要新的 Input System 包。旧版
Input.GetAxis()无法使用。 - 跳过设备验证 —— 读取功能前务必检查
InputDevice.isValid;设备可能随时断开连接。 - 忽略 Socket 上的 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 的瞬时传送会导致晕动症。
- 将 Poke Interactor 与 UI Toolkit 搭配使用 —— 这是已知限制;请改用基于 Canvas 的 UI,并搭配 Tracked Device Graphic Raycaster。
关键 API 快速参考
| 类 | 命名空间 | 用途 |
|---|---|---|
XROrigin | Unity.XR.CoreUtils | 相机 Rig 和追踪空间 |
XRInteractionManager | UnityEngine.XR.Interaction.Toolkit | 协调交互 |
XRBaseInteractor | UnityEngine.XR.Interaction.Toolkit | Interactor 基类 |
XRBaseInteractable | UnityEngine.XR.Interaction.Toolkit | 可交互对象基类 |
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 着色器注意事项