Bring your SceneKit project to RealityKit
2025年6月9日
一句话判断
SceneKit 正式 soft deprecated 了。现有 app 不会挂,但别指望新功能。如果你手上还有 SceneKit 项目,这是 Apple 给你的官方迁移指南——从资产转换到后处理 bloom,手把手把一个完整游戏搬到 RealityKit。
这场 Session 讲了什么
Max Cobb 把一个经典的 SceneKit 示例游戏(红色小熊猫 PyroPanda 在火山场景中解谜)完整迁移到了 RealityKit,覆盖了资产、场景、动画、灯光、音频、视觉特效六大环节。
核心架构差异: SceneKit 是 node-based,所有东西挂在节点上(geometry、animation、audio、physics、light 都是节点属性)。RealityKit 是 ECS(Entity Component System),行为通过挂载 Component 实现。坐标系完全一致(Y-up, Z-toward-camera),这部分零成本迁移。
资产转换: SceneKit 用 SCN 格式,RealityKit 用 USD。三条路径:1)有原始文件的话直接从 DCC 工具(Blender 等)导出 USD;2)Xcode 里 File -> Export 选 USD Package;3)xcrun scntool --convert 命令行转换,支持 --append-animation 把分散的 SCN 动画文件合并到一个 USD 里。
场景搭建用 Reality Composer Pro。 它是 Xcode 和 DCC 工具之间的桥梁——可以编辑材质、shader、粒子、灯光,项目本身是 Swift Package,在 Xcode 中作为 local dependency 引入。加载代码极其简单:
RealityView { content in
let scene = try await Entity(named: "PyroPanda", in: pyroPandaBundle)
content.add(scene)
}
动画通过 AnimationLibraryComponent 访问。 USD 文件中的动画会自动注册到组件中,按名称播放。比 SceneKit 需要遍历节点树找 SCNPlayer 方便得多。
灯光、音频都走 Component 模式。 灯光有 DirectionalLightComponent + DirectionalLightShadowComponent。音频有 AudioLibraryComponent,支持流式播放和循环,可以在 Reality Composer Pro 中全部配置好,运行时零额外代码。
Post-processing bloom 是最后的点睛之笔。通过 PostProcessEffect protocol + Metal Performance Shaders 实现高光溢出效果。三步:提取高光 -> 高斯模糊 -> 合成回原图。
值得深挖的点
SceneKit deprecation 的真实含义。 这是 soft deprecation:现有 app 继续运行,Apple 只修 critical bug,不再有新功能。没有 hard deprecation 的时间表,但如果你在规划新项目或大版本更新,别再选 SceneKit。
scntool 的 append-animation 是关键。 SceneKit 常见模式是把角色几何体和各动画分别存成 SCN 文件。scntool 能把多个动画追加到一个 USD 文件中,在 RealityKit 中通过 AnimationLibraryComponent 统一管理。
Reality Composer Pro 不是必须的。 你可以纯代码搭建 RealityKit 场景。但对可视化调试和材质编辑来说,RCP 省很多事。
PostProcessEffect 在 iOS/iPadOS/macOS/tvOS 上可用,但 visionOS 上目前不支持。 如果你的 app 要跨平台,需要条件编译处理 bloom 效果。
代码片段
SCN 到 USD 转换(含动画合并):
# 基础转换
xcrun scntool --convert max.scn --format usdz --output ~/Desktop/max.usdz
# 追加多个动画文件
xcrun scntool --convert max.scn --format usdz \
--append-animation max_walk.scn \
--append-animation max_spin.scn \
--output ~/Desktop/max.usdz
播放 AnimationLibraryComponent 中的动画:
// SceneKit 旧写法
let root = scene.rootNode.childNode(withName: "Max_rootNode", recursively: true)
let player = animationScene.rootNode.animationPlayers.first
root?.addAnimationPlayer(player!, forKey: "spin")
player?.play()
// RealityKit 新写法
let max = scene.findEntity(named: "Max")!
let animLib = max.components[AnimationLibraryComponent.self]!
let spin = animLib.animations["spin"]!
try max.playAnimation(spin)
用 PlayAudioAction 简化音频播放:
// 不需要手动拿 AudioLibraryComponent
let action = PlayAudioAction(target: terrainEntity, resourceName: "ambient")
let animation = action.createAnimation()
terrainEntity.playAnimation(animation)
最佳实践
先盘点资产再动手。 列出所有 SCN 文件、动画文件、粒子文件、shader 代码。有原始 DCC 文件的优先从源头导出 USD,转换质量最好。
scntool 转换后检查材质。 SCN 的某些材质属性(如自定义 shader)在 USD 中没有直接对应,可能需要在 Reality Composer Pro 中手动调整。
音频流式加载大文件。 AudioLibraryComponent 默认会预加载整个音频文件到内存。对于长音频(背景音乐、环境音),在 Reality Composer Pro 中勾选 “Stream” 避免内存爆炸。
跨平台要注意 View 差异。 SceneKit 用 SCNView/SceneView,RealityKit 统一用 RealityView。RealityView 自动适配 visionOS 立体渲染,无需额外代码。
Bloom 后处理用 Metal Performance Shaders 起步。 不需要从头写 shader,Apple 提供了高斯模糊等优化过的 MPS,组合起来就能实现专业级 bloom。
还有什么值得关注
- RealityKit 今年扩展到 tvOS,你的 3D 游戏可以在 Apple TV 上跑。配合 game controller 支持。
- visionOS 上可以做 progressive immersion portal——把 RealityKit 场景放进一个可调节大小的传送门里,沉浸感拉满。
- 完整的 PyroPanda 示例代码已开放下载,包含了角色移动、camera 跟随、game controller 输入等 Session 中没时间细讲的内容。
- 配套视频推荐:“What’s New in RealityKit”(Session 287)和往年的 Reality Composer Pro 入门。