Discover RealityKit APIs for iOS, macOS, and visionOS
Spatial Computing 进阶 20m

探索 RealityKit 跨平台 API

Discover RealityKit APIs for iOS, macOS, and visionOS

2024年6月10日

在 Apple 官方观看视频

一句话判断

RealityKit 今年一口气加了 hover effects 自定义、Spatial Tracking API、力场效果、物理关节、动态光源和阴影、以及 Portal 增强,几乎补全了做一个完整空间计算游戏所需的全部能力。

这场 Session 讲了什么

这个 Session 用一个”太空飞船”游戏的构建过程,串联了 RealityKit 今年新增的六大能力模块。游戏从一个 volume 里展示飞船模型开始,玩家可以用手势控制飞船在混合沉浸空间中飞行,穿越小行星带,最后通过传送门进入外太空场景。

每个游戏环节对应一个 RealityKit 新 API:hover effects 让模型在被注视时产生视觉反馈;Spatial Tracking Session 简化了手部追踪的接入流程;force effects 和 joints 带来了物理模拟能力(飞船引擎推力、小行星碰撞);动态光源和阴影增强了空间感知;Portal API 的增强让飞船可以真正”飞入”传送门到达另一个场景。

整套 API 在 iOS、macOS 和 visionOS 上通用,Apple 特别强调了跨平台能力。

值得深挖的点

HoverEffectComponent 的三种样式:从默认到完全自定义

visionOS 上 3D 内容的 hover 反馈一直是个痛点。默认的 spotlight 效果太”系统化”,和游戏或定制化 App 的视觉风格格格不入。今年新增了 highlight 和 shader 两种样式。

Highlight 样式可以对整个 mesh 施加统一的颜色高亮,支持自定义颜色和强度。用三行代码就能让飞船在被注视时发出暖黄色光芒。比 spotlight 适合游戏场景。

但真正有杀伤力的是 shader 样式。它把 HoverState 节点暴露给 Reality Composer Pro 的 shader graph,让你用可视化的节点编辑器设计任意复杂的注视效果。Session 里的示例是”注视时飞船舷窗亮起”——intensity 值从 0 到 1 的动画驱动了一个 Mix 节点,混合飞船的自发光颜色。这种程度的定制在去年完全做不到。

HoverState 节点还提供了位置信息(注视点的 3D 坐标),所以你可以做”目光扫过时产生光晕跟随”之类的效果。另一个同事用它做了一个”沿 3D 笔刷扫过的紫色光带”效果。

SpatialTrackingSession:手部追踪的简化接入

在 visionOS 1.0 上做手部追踪,需要直接调用 ARKit 的 API,处理 session 管理、权限请求、anchor 更新等底层细节。RealityKit 今年推出了 SpatialTrackingSession,把权限管理和 hand anchor 统一封装了。

使用方式很直观:创建 session、请求手部追踪权限、然后为每个需要追踪的手指关节创建 anchor entity。在自定义 System 的 update 函数里,通过 Entity.position 查询 anchor 的实时位置。

Session 展示了如何用两个手指(拇指尖和食指尖)的距离来控制飞船的油门——距离越近飞得越快。右手的倾斜角度控制飞船方向。这个输入模型非常适合 VR 场景:不需要额外的控制器,用户的双手就是最自然的输入设备。

代码片段

自定义 highlight hover 效果

场景:让飞船模型在被注视时显示暖黄色高亮。

// 创建自定义高亮样式
let style = HighlightHoverEffectStyle(
    color: .yellow,
    strength: 0.8
)
// 应用到飞船 entity
let hoverComponent = HoverEffectComponent(style: style)
spaceship.components.set(hoverComponent)

坑:strength 设太高会显得刺眼,建议从 0.5-0.8 开始调试。

用手指距离控制飞船速度

场景:左手拇指和食指捏合控制油门。

// 为左手的拇指尖和食指尖创建 anchor
let thumbAnchor = AnchorEntity(hand: .left, joint: .thumbTip)
let indexAnchor = AnchorEntity(hand: .left, joint: .indexFingerTip)

// 在 System update 中计算距离
func update(context: SceneUpdateContext) {
    let thumbPos = thumbAnchor.position(relativeTo: nil)
    let indexPos = indexAnchor.position(relativeTo: nil)
    let distance = distance(thumbPos, indexPos)

    // 距离越近,油门越大
    let throttle = mapDistanceToThrottle(distance)

    // 沿飞船前进方向施加力
    let force = spaceship.forward * throttle
    spaceship.components[PhysicsBodyComponent.self]?.applyForce(force)
}

坑:手部追踪的 anchor 位置可能有轻微抖动,建议对 throttle 值做平滑处理。

Shader 样式的 hover 效果

场景:在 Reality Composer Pro 的 shader graph 里用 HoverState 节点。

// shader graph 里已经定义了 HoverState → Mix → emissive color 的节点图
// 代码里只需要指定 shader 样式
let shaderStyle = ShaderHoverEffectStyle()
let component = HoverEffectComponent(style: shaderStyle)
spaceship.components.set(component)

坑:shader graph 里的 HoverState 节点需要在 Reality Composer Pro 中设置,不是纯代码能完成的。

最佳实践

新项目:如果你在做 visionOS 上的 3D 交互应用,hover effects 应该作为标配加入——没有视觉反馈的 3D 内容会让用户困惑”这是能交互的吗”。手部追踪用 SpatialTrackingSession 而不是直接调 ARKit,代码更少、维护更简单。物理模拟场景优先考虑 force effects 而不是手动计算位置——让 RealityKit 的物理引擎替你处理碰撞和运动。

已有项目:如果已经用 ARKit 做了手部追踪,可以考虑迁移到 SpatialTrackingSession,减少代码量。hover effects 的迁移成本很低——给现有 entity 加一个 component 就行。Portal API 的增强是渐进式的,不需要重写现有的 portal 代码就能获得新的穿透效果。

还有什么值得关注

  • 动态光源和阴影在空间计算中不是锦上添花——没有阴影,用户很难判断物体之间的距离关系。
  • Portal API 的增强允许物体在 portal 边界处被正确裁剪,飞船可以”飞入”portal 而不是被挡在边界外。
  • 所有新 API 都是跨平台的:iOS、macOS、visionOS 共用同一套接口,代码可以复用。
WWDC 2024