Highlight
ARKit 和 RealityKit 在 visionOS 上已深度集成到操作系统中,世界追踪和场景理解变成系统服务,应用免费获得摄像头穿透、手部遮挡和 World Map 自动持久化能力。iOS AR 应用迁移需要理解新的空间展示方式、RealityView 替代 ARView、以及 Data Provider 取代 Configuration 的 API 变化。
核心内容
ARKit 三大核心概念的演进
(00:25)ARKit 2017 年在 iOS 上引入时,定义了三个核心概念:
- World Tracking:六自由度追踪设备位置,将虚拟内容锚定到现实世界
- Scene Understanding:提供周围环境的语义信息,让内容智能放置、与周围真实交互
- Rendering Registration:通过相机变换和内参,正确注册和合成虚拟内容
在 visionOS 上,这些概念全部保留,但实现方式发生了根本性变化。
系统级服务化
(01:34)ARKit 的追踪和场景理解现在作为系统服务运行,支撑从窗口放置到空间音频的一切功能。系统承担了原本属于应用的责任:
- 摄像头穿透(camera pass-through)内置,应用免费获得
- 手部遮挡(hand matting)内置,应用免费获得
- World Map 由系统服务持续持久化,应用不再需要自己处理
这让开发者可以专注于构建内容和体验。
三种空间展示方式
(04:25)
Shared Space:应用并列运行,类似 Mac 桌面。应用可以打开一个或多个窗口,也可以创建三维 Volume。内容限制在各自边界内,与其他应用共享空间。
Volume:在 Shared Space 中展示 3D 内容的容器。例如,一个窗口显示棋盘游戏列表,另一个窗口显示规则,选中的游戏在独立的 Volume 中打开。
Full Space:应用独占整个空间,只有该应用的窗口、Volume 和 3D 对象可见。在 Full Space 中,应用可以使用 AnchorEntity 将内容固定到桌子、地板等表面,也可以访问 ARKit 数据。
RealityView:SwiftUI 与 RealityKit 的桥梁
(08:44)RealityView 是替代 iOS 上 ARView 的新 SwiftUI 视图。它同时容纳 2D 和 3D 元素,让用户可以用系统手势与实体交互。
RealityView 与 ARView 的对比:
| 特性 | ARView (iOS) | RealityView (visionOS) |
|---|---|---|
| 容器类型 | Scene | Content |
| 手势支持 | 触摸手势 | 空间手势(伸手选择/拖拽) |
| 锚定实体 | 需要 ARSession + 权限 | 系统服务支持,无需权限 |
| 底层追踪 | ARSession | 系统服务 |
(10:09)RealityKit 的 Entity Component System 仍然适用:实体是 3D 内容的容器,组件定义外观和行为(ModelComponent、CollisionComponent 等),系统操作具有所需组件的实体。
AnchorEntity 的隐私友好设计
(14:19)在 visionOS 上,AnchorEntity 可以在不请求用户权限的情况下使用。系统找到目标(如桌子)并自动锚定内容,但不会向应用透露底层变换数据。
新的 AnchorEntity 目标包括手部——可以锚定内容到手掌或手腕,内容会跟随手部移动。
不同 AnchorEntity 的子实体之间互不可见,因为它们各自处于不同的坐标空间中。
Raycasting 在空间计算中的新形态
(17:01)在 iOS 上,raycasting 将 2D 输入转换为 3D 位置。在 visionOS 上,用户可以直接用手与内容交互,但 raycasting 仍然有用——它让用户可以触及手臂长度之外的物体。
两种 raycasting 方式:
系统手势 raycasting:给实体添加 CollisionComponent 和 InputTargetComponent,添加 SpatialTapGesture 到 RealityView。用户凝视实体并轻触,事件返回世界空间中的位置。
手部数据 raycasting:使用 ARKit hand anchors 获取手指关节信息,构建射线的起点和方向,对场景中的实体执行 raycast。
ARKit API 重构:Data Provider 模式
(22:08)iOS 上的 ARKit 使用 Configuration 模式:
// iOS 方式(已废弃)
let configuration = ARWorldTrackingConfiguration()
configuration.sceneReconstruction = .mesh
configuration.planeDetection = [.horizontal, .vertical]
let session = ARSession()
session.run(configuration)
visionOS 改用 Data Provider 模式:
// visionOS 方式
let sceneReconstruction = SceneReconstructionProvider(modes: [.classification])
let planeDetection = PlaneDetectionProvider(alignments: [.horizontal, .vertical])
let session = ARKitSession()
try await session.run([sceneReconstruction, planeDetection])
关键点:
- 每个能力有独立的 Data Provider
- 手部追踪也有独立的 Provider
- Provider 初始化时配置参数
ARKitSession.run()接收 Provider 数组
锚点更新的异步发布
(23:50)iOS 上,单个 delegate 接收聚合在 ARFrame 中的锚点更新。visionOS 上,每个 Data Provider 独立异步发布锚点更新:
SceneReconstructionProvider发布MeshAnchorPlaneDetectionProvider发布PlaneAnchor- 无需类型区分
- 锚点更新与其他 Provider 解耦,延迟更低
- ARFrame 不再提供,因为系统自动处理显示
World Anchor 持久化
(25:12)iOS 上,应用需要自己处理 World Map 和锚点持久化:请求、保存、加载、等待重定位。
visionOS 上,系统在后台持续持久化 World Map,自动加载、卸载、创建和重定位。应用只需关注 World Anchor 本身:
// 使用 WorldTrackingProvider 添加 WorldAnchor
let worldTracking = WorldTrackingProvider()
try await session.run([worldTracking])
let anchor = WorldAnchor(originFromAnchorTransform: placementTransform)
try await worldTracking.add(anchor)
系统会自动保存这些锚点。当设备回到相同环境时,应用会自动收到之前持久化的锚点更新。
详细内容
从 ARKit Mesh Anchor 构建碰撞实体
(18:17)场景重建数据以 mesh chunks 形式交付。为每个 chunk 创建实体:
// 创建表示 mesh chunk 的实体
let entity = Entity()
// 使用 mesh anchor 的变换放置实体
entity.transform = Transform(matrix: meshAnchor.originFromAnchorTransform)
// 从 mesh anchor 生成碰撞形状
let shape = try await ShapeResource.generateStaticMesh(from: meshAnchor)
entity.components[CollisionComponent.self] = CollisionComponent(shapes: [shape])
// 添加 InputTargetComponent 支持手势交互
entity.components[InputTargetComponent.self] = InputTargetComponent()
关键点:
originFromAnchorTransform将实体正确放置在 Full Space 中ShapeResource.generateStaticMesh从 mesh anchor 生成碰撞形状CollisionComponent让实体支持 hit testingInputTargetComponent让实体可以接收系统手势- 场景重建数据会更新,需要监听变化并更新实体
使用手部数据执行 Raycast
// 获取手指关节位置构建射线
let handAnchor = latestHandAnchors.left
if let indexTip = handAnchor.handSkeleton?.joint(.indexTip),
let indexIntermediate = handAnchor.handSkeleton?.joint(.indexIntermediate) {
let origin = indexTip.anchorFromJointTransform.columns.3.xyz
let direction = normalize(
indexIntermediate.anchorFromJointTransform.columns.3.xyz - origin
)
// 执行 raycast
let hits = content.entities(
raycastingFrom: origin,
in: direction,
length: 10.0
)
if let hit = hits.first {
// 在命中位置放置 WorldAnchor
let anchor = WorldAnchor(originFromAnchorTransform: hit.position)
try await worldTracking.add(anchor)
// 创建实体并设置变换
let modelEntity = try Entity.load(named: "ship")
modelEntity.transform = Transform(matrix: anchor.originFromAnchorTransform)
content.add(modelEntity)
}
}
关键点:
- 从手指关节获取射线起点和方向
raycastingFrom:in:length:对场景实体执行 raycastCollisionCastHit提供命中实体、位置和表面法线- 使用
WorldAnchor让内容持续锚定到现实世界 - ARKit 更新 WorldAnchor 时,同步更新实体变换
核心启发
1. 将 iOS AR 家具摆放应用迁移到 visionOS
- 做什么:把现有的 AR 家具预览应用带到 visionOS,让用户在 Shared Space 中查看家具,在 Full Space 中放置到真实房间
- 为什么值得做:系统免费处理 World Map 持久化,AnchorEntity 无需权限即可锚定到桌面。用户可以直接用手抓取和放置家具
- 怎么开始:用 RealityView 替换 ARView,在 Shared Space 中用 Volume 展示家具模型,切换到 Full Space 后用 AnchorEntity 或 ARKit PlaneAnchor 放置
2. 构建手势驱动的 3D 内容创作工具
- 做什么:让用户用手势在真实环境中放置、缩放和旋转 3D 模型
- 为什么值得做:ARKit 手部追踪提供完整骨骼数据,RealityKit 的碰撞系统支持 raycast 交互。系统手势让用户可以自然地伸手选择物体
- 怎么开始:在 Full Space 中运行 ARKitSession,订阅 HandTrackingProvider 获取手部数据,用 finger joint 位置构建射线,对 mesh entities 执行 raycast
3. 创建持久化的空间笔记应用
- 做什么:让用户在真实环境中的特定位置留下虚拟笔记或标记
- 为什么值得做:WorldAnchor 自动持久化,用户回到同一位置时笔记自动出现。系统处理所有 World Map 管理,应用只需关注锚点本身
- 怎么开始:使用 WorldTrackingProvider 添加 WorldAnchor,用锚点的 identifier 关联笔记内容,监听锚点更新来加载/显示对应笔记
4. 开发协作式空间设计评审工具
- 做什么:让设计团队在 3D 空间中共同评审建筑或产品设计
- 为什么值得做:Shared Space 中多个应用可以并排运行,团队成员可以同时查看设计文档和 3D 模型。Full Space 模式允许将设计锚定到真实桌面进行 1:1 比例评审
- 怎么开始:在 Shared Space 中用窗口展示设计文档,用 Volume 展示 3D 模型。切换到 Full Space 后用 AnchorEntity 将模型锚定到桌面
关联 Session
- Meet ARKit for spatial computing — ARKit 空间计算新 API 详解
- Meet RealityKit for spatial computing — RealityKit 空间计算新特性
- Go beyond the window with SwiftUI — SwiftUI 空间场景类型详解
评论
GitHub Issues · utterances