探索 RealityKit 跨平台 API
Discover RealityKit APIs for iOS, macOS, and visionOS
2024年6月10日
一句话判断
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 共用同一套接口,代码可以复用。