System & Services 进阶 20m
开发你的第一个沉浸式应用
Develop your first immersive app
2023年6月5日
一句话判断
这场 Session 是空间计算平台的入门指南——从 Xcode 项目创建到 RealityView 的使用,再到 SwiftUI 手势与 RealityKit 实体的绑定,每一步都有清晰的代码示例。如果你打算做 visionOS 开发,从这里开始。
这场 Session 讲了什么
Session 系统性地介绍了在空间计算平台上开发 App 的完整流程:
项目创建: Xcode 新项目模板提供了两个关键选项:
- Initial Scene:Window(2D 内容,平面可调,深度固定)或 Volume(3D 内容,三维尺寸由 App 控制)。
- Immersive Space:None(不添加)、Mixed(虚拟内容叠加在透视环境上)、Progressive(约 180 度视口,用数码表冠调节)、Full(完全沉浸,隐藏透视)。
开发工具链:
- Simulator:在模拟场景中体验 App。
- Xcode Previews:快速迭代 UI。
- Reality Composer Pro:新工具,用于准备和预览空间内容。
核心 API:
- RealityView:SwiftUI 中嵌入 RealityKit 内容的容器。包含
make闭包(初始化内容)和update闭包(响应 SwiftUI 状态变化)。 - RealityKit Content Package:项目自动包含的内容包,由 Reality Composer Pro 管理。
- 手势绑定:SwiftUI 手势可以精确绑定到 RealityKit 实体上(
.gesture()修饰符直接作用于三维实体)。
设计原则:
- App 应始终从 Window 开始,提供清晰的进入和退出沉浸模式的控制。
- 不要在用户不知情的情况下强制进入沉浸模式。
- 沉浸模式激活时,App 从 Shared Space 进入 Full Space,其他 App 被隐藏。
值得深挖的点
四种场景类型的设计层次是一个从”最小侵入”到”完全沉浸”的渐进光谱。Window 最安全,用户始终能看到周围环境;Volume 是 3D 内容的安全展示方式;Mixed Immersion 在保留环境感知的同时放置虚拟内容;Full Immersion 把用户完全带入虚拟世界。Apple 的建议是让用户自己决定何时进入哪种状态——这是对用户控制权的尊重。
RealityView 的 update 闭包不是渲染循环——这个区别至关重要。它只在 SwiftUI 状态变化时调用,不是每帧调用。如果你需要持续动画或物理模拟,应该在 RealityKit 层面处理,而不是依赖 update 闭包。
SwiftUI 手势直接绑定到 RealityKit 实体是空间交互的关键。在 2D 平台上手势作用于 View,在空间计算平台上手势可以作用于三维空间中的特定实体。这意味着你可以对不同的 3D 对象分别绑定不同的手势处理逻辑。
代码片段
RealityView 的基本结构:
import SwiftUI
import RealityKit
struct ContentView: View {
@State private var enlarge = false
var body: some View {
VStack {
// RealityView:SwiftUI 中的 3D 内容容器
RealityView { content in
// make 闭包:初始化 3D 内容
if let entity = try? await ModelEntity(named: "Scene") {
content.add(entity)
}
} update: { content in
// update 闭包:响应 SwiftUI 状态变化
if let entity = content.entities.first {
entity.scale = enlarge ? SIMD3(1.5, 1.5, 1.5) : SIMD3(1, 1, 1)
}
// 注意:这不是渲染循环,只在状态变化时调用
}
// 控制按钮
Toggle("放大", isOn: $enlarge)
.glassBackgroundEffect() // 玻璃背景效果,确保按钮清晰可读
}
}
}
SwiftUI 手势绑定到 RealityKit 实体:
RealityView { content in
if let entity = try? await ModelEntity(named: "MyModel") {
content.add(entity)
}
}
.gesture(
// 手势直接作用于 RealityKit 实体
SpatialTapGesture()
.targetedToAnyEntity() // 可以精确指向特定实体
.onEnded { value in
// 获取被点击的三维实体
let entity = value.entity
// 在三维空间中执行操作
entity.orientation = simd_quatf(angle: .pi / 4, axis: [0, 1, 0])
}
)
最佳实践
- App 始终从 Window 或 Volume 开始,提供明确的按钮让用户进入沉浸模式。
- 不要自动激活 Immersive Space,让用户主动选择。
- RealityView 的 update 闭包只用于响应 SwiftUI 状态变化,不要把它当作渲染循环。
- 使用 Reality Composer Pro 准备 3D 内容,比纯代码创建更直观。
- 手势使用
.targetedToAnyEntity()可以精确绑定到被触碰的 3D 实体。 - 在 Simulator 中测试时注意性能表现可能与真机有差异。
还有什么值得关注
- “Meet SwiftUI for spatial computing” Session 详细介绍了 Window 场景类型。
- “Take SwiftUI to the next dimension” Session 聚焦 Volume 场景。
- “Go beyond the window with SwiftUI” Session 深入讲解 Immersive Space。
- Reality Composer Pro 是全新的内容创作工具,支持预览空间内容在真实环境中的表现。
- ARKit 的手部追踪等高级功能只在 Full Space 中可用,且需要用户授权。
WWDC 2023