Highlight
RealityKit 2025 把 ARKit 数据通过
AnchorStateEvents直接暴露给应用,并用ManipulationComponent.configureEntity()一行代码完成 3D 物体的抓取、旋转与双手交接。
核心内容
过去做一个能放在桌面上、可以伸手抓取、又能正确被现实物体遮挡的小游戏,开发者要同时管 ARKit session、RealityKit 场景、自定义手势识别、物理状态切换。一套流程下来,胶水代码远多于业务代码。今年 RealityKit 把这些环节直接做进了框架。
Laurence 用一个空间解谜游戏把所有新特性串了起来:宝箱锚定在桌面上,玩家抓起周围的小物件去找钥匙,找到后宝箱打开放出小烟花。游戏里用到的能力,恰好覆盖了 RealityKit 2025 的更新清单——SpatialTrackingSession 直接产生 AnchorStateEvents,ManipulationComponent 接管抓取交互,SceneUnderstandingFlags 让真实房间网格参与物理模拟,EnvironmentBlendingComponent 让虚拟物体被现实静态物遮挡,MeshInstancesComponent 用 GPU instancing 高效渲染装饰物,ImagePresentationComponent 与 VideoPlayerComponent 处理空间照片和沉浸式视频。另外,RealityKit 今年开始支持 tvOS,覆盖所有代次的 Apple TV 4K。
详细内容
ARKit 数据直通 RealityKit。 以前要并行跑 ARKit session 和 RealityKit 场景,现在通过 SpatialTrackingSession 启动追踪,再用 AnchorEntity 描述要找什么样的锚点,命中后通过 AnchorStateEvents.DidAnchor 直接拿到 ARKit 原始数据(04:33)。
// Set up SpatialTrackingSession
@State var spatialTrackingSession = SpatialTrackingSession()
RealityView { content in
let configuration = SpatialTrackingSession.Configuration(
tracking: [.plane]
)
if let unavailableCapabilities = await spatialTrackingSession.run(configuration) {
// Handle errors
}
}
关键点:
SpatialTrackingSession.Configuration用tracking: [.plane]声明只追踪平面,按需开关能减少耗电。run(configuration)是 async 方法,返回值为unavailableCapabilities,里面是当前设备不支持的能力,开发者要在这里降级。- session 必须放在
RealityView的闭包里启动,确保和当前 immersive scene 同生命周期。
拿到锚点事件后,可以直接 cast 到 ARKit 的 PlaneAnchor 用原生 transform(05:48):
didAnchor = content.subscribe(to: AnchorStateEvents.DidAnchor.self) { event in
guard let anchorComponent =
event.entity.components[ARKitAnchorComponent.self] else { return }
guard let planeAnchor = anchorComponent.anchor as? PlaneAnchor else { return }
let worldSpaceFromExtent =
planeAnchor.originFromAnchorTransform *
planeAnchor.geometry.extent.anchorFromExtentTransform
gameRoot.transform = Transform(matrix: worldSpaceFromExtent)
// Add game objects to gameRoot
}
关键点:
event.entity.components[ARKitAnchorComponent.self]是 RealityKit 新加的桥接组件,承载 ARKit 原始锚点。anchorComponent.anchor类型为ARAnchor,需要按业务需要 cast 到PlaneAnchor、ImageAnchor等具体类型。originFromAnchorTransform * anchorFromExtentTransform把游戏根节点对齐到平面 extent 的中心,避免模型半截悬空。
ManipulationComponent 接管抓取。 一行 ManipulationComponent.configureEntity() 就能让任意 entity 支持抓取、旋转,甚至双手交接(07:38):
extension Entity {
static func loadModelAndSetUp(modelName: String,
in bundle: Bundle) async throws -> Entity {
let entity = // Load model and assign PhysicsBodyComponent
let shapes = // Generate convex shape that fits the entity model
ManipulationComponent.configureEntity(entity, collisionShapes: [shapes])
var manipulationComponent = ManipulationComponent()
manipulationComponent.releaseBehavior = .stay
entity.components.set(manipulationComponent)
return entity
}
}
关键点:
configureEntity内部一次性挂载InputTargetComponent、CollisionComponent、HoverEffectComponent与ManipulationComponent,省掉手动配置。releaseBehavior = .stay让物体松手后留在原地,默认值会自动飘回起点,不适合解谜场景。- 抓取时机要配合
ManipulationEvents切换物理模式(09:28),抓起时设kinematic,松手时设dynamic让重力接管。
Scene Understanding 参与物理模拟。 在 SpatialTrackingSession.Configuration 里加上 sceneUnderstanding: [.collision, .physics](10:52),房间真实网格直接进入物理世界,物体掉到地上会被真地板接住。
EnvironmentBlendingComponent 处理静态遮挡。 preferredBlendingMode: .occluded(by: .surroundings)(11:56)让虚拟实体被真实静态物体精确遮挡,但人和宠物等动态对象不参与遮挡。挂了这个组件的实体会被当成背景层,永远绘制在其他虚拟物体后面。
MeshInstancesComponent 大批量装饰物。 用一个 entity 加一组 transform 矩阵就能渲染上百个相同模型(14:20),相比克隆 entity 在内存占用和 draw call 上都省得多。LowLevelInstanceData(instanceCount:) 给出可写入的 transform 缓冲。
ImagePresentationComponent 处理三种图像。 普通 2D 图片、spatial photo、以及由 2D 图片生成的 spatial scene。设 desiredViewingMode 之前要先用 availableViewingModes.contains(.spatialStereo) 检查(17:57),否则会回退到 2D。spatial scene 通过 ImagePresentationComponent.Spatial3DImage 调 generate() 生成,效果与系统 Photos app 一致。
VideoPlayerComponent 扩展。 支持 spatial video 完整空间样式、APMP 180/360/Wide-FOV、Apple Immersive Video,并自动调节舒适度。
Entity 直接从 Data 加载。 Entity(from: data) 让模型可以从网络流直接构造(23:35),不用再先落盘再加载。
核心启发
-
把 ARKit 接入 RealityKit 当默认起手式。新建空间项目时,直接用
SpatialTrackingSession+AnchorStateEvents取代手动维护的 ARKit session。为什么值得做:少一份并行的状态管理,锚点生命周期与 entity 生命周期天然绑定。怎么开始:把现有ARSession.run替换为SpatialTrackingSession.run,订阅DidAnchor/WillUnanchor/DidFailToAnchor三个事件。 -
用 ManipulationComponent 替换自写的拖拽手势。为什么值得做:双手交接、惯性、视觉 hover 效果都是免费送的,自己实现要写几百行手势代码。怎么开始:找到项目里所有
DragGesture/SpatialTapGesture处理 3D 物体的地方,换成ManipulationComponent.configureEntity(entity, collisionShapes:),再用ManipulationEvents.WillBegin/WillEnd切换PhysicsBodyComponent.mode。 -
打开 Scene Understanding 的 collision/physics 标志。为什么值得做:让虚拟物体真的能”放在”现实桌子上,比手动检测平面再做碰撞稳定得多。怎么开始:在
SpatialTrackingSession.Configuration里加sceneUnderstanding: [.collision, .physics],给会落地的物体配PhysicsBodyComponent(mode: .dynamic)。 -
用 MeshInstancesComponent 渲染场景装饰。为什么值得做:克隆 entity 在 visionOS 上 draw call 涨得很快,instancing 在几十上百个实例时帧率明显更稳。怎么开始:把重复的
Entity.clone(recursive:)改成MeshInstancesComponent,用LowLevelInstanceData.withMutableTransforms批量写 transform 矩阵。 -
检查 availableViewingModes 后再设 desiredViewingMode。为什么值得做:spatial photo 不一定支持每种 viewing mode,盲设会静默回退。怎么开始:所有
ImagePresentationComponent的初始化代码加一道availableViewingModes.contains(...)守卫。
关联 Session
- Better together: SwiftUI and RealityKit — ManipulationComponent 在 SwiftUI 视图里的完整用法
- Bring your SceneKit project to RealityKit — SceneKit 项目迁移到 RealityKit 的实操路径
- Discover Metal 4 — Metal 4 新特性,配合 RealityKit 自定义渲染时用得上
- Combine Metal 4 machine learning and graphics — 把机器学习塞进图形管线的方法
- Engage players with the Apple Games app — 新的 Games app 入口与玩家发现机制
评论
GitHub Issues · utterances