WWDC Quick Look 💓 By SwiftGGTeam
Dive into RealityKit 2

Dive into RealityKit 2

观看原视频

Highlight

RealityKit 2 引入了自定义系统、PhysicallyBasedMaterial、动画混合层、角色控制器和运行时资源生成,让 AR 应用开发从”放置模型”升级到”构建完整交互体验”。

核心内容

RealityKit 2019 年发布时,定位是”让 AR 开发变简单”。加载 USDZ 模型、放到检测到的平面上,几行代码就能跑起来。

但开发者反馈很明确:我们需要更多控制权。自定义着色器、自定义游戏逻辑、更灵活的动画、物理交互——这些在 RealityKit 1 中很难实现。

WWDC2021 的回应是 RealityKit 2。Session 用一个水下 AR 演示贯穿全程:鱼群在客厅中游动,潜水员在沙发和地板间跳跃,章鱼在受到惊吓时变色逃走。所有这些效果都用新 API 实现。

详细内容

自定义系统:纯 ECS 架构

RealityKit 2 向更纯粹的 ECS(Entity Component System)架构演进。功能放在 System 中,状态放在 Component 中,Entity 只是组件的标识符。

class FlockingSystem: RealityKit.System {
    required init(scene: RealityKit.Scene) { }

    static var dependencies: [SystemDependency] { [.before(MotionSystem.self)] }

    private static let query = EntityQuery(where: .has(FlockingComponent.self)
                                                && .has(MotionComponent.self)
                                                && .has(SettingsComponent.self))

    func update(context: SceneUpdateContext) {
        context.scene.performQuery(Self.query).forEach { entity in
            guard var motion: MotionComponent = entity.components[MotionComponent.self]
                else { continue }

            // Boids 模拟:分离、聚合、对齐
            motion.forces.append(/* forces */)

            entity.components[MotionComponent.self] = motion
        }
    }
}

关键点:

  • 自定义系统遵循 RealityKit.System 协议(07:10)
  • dependencies 指定执行顺序,.before(MotionSystem.self) 确保本系统在运动系统之前运行
  • EntityQuery 高效筛选参与系统的实体,无需遍历整个场景图
  • Component 是 Swift struct(值类型),修改后需要写回 entity
  • 符合 Codable 的 Component 在多玩家 AR 中自动网络同步(08:15)

架构变化:Game Manager 角色弱化

以前,每帧的更新逻辑写在 SceneEvents.update 的闭包中,通常集中在 Game Manager 类里。现在,更新逻辑被拆分到独立的 System 中,由引擎按依赖顺序调用。

以前,通过 Entity 子类的协议遵循来表达组件组合。现在不需要子类化 Entity 了,组件可以在运行时动态添加和移除。

// 新方式:运行时添加/移除组件
entity.components[FlockingComponent.self] = FlockingComponent()
entity.components[FlockingComponent.self] = nil

关键点:

  • Game Manager 只需给 Entity 添加 Component,System 自动处理逻辑(10:15)
  • Entity 子类化不再是必须的
  • TransientComponent:克隆 Entity 时不继承的组件,如临时状态标记(11:25)
  • storeWhileEntityActive:事件订阅随 Entity 生命周期自动管理(11:58)

SwiftUI 与 RealityKit 的数据传递

用 SwiftUI 构建设置面板,将数据传递到 RealityKit 的自定义系统中。

class Settings: ObservableObject {
    @Published var separationWeight: Float = 1.6
}

struct ContentView: View {
    @StateObject var settings = Settings()
    var body: some View {
        ZStack {
            ARViewContainer(settings: settings)
            MovementSettingsView()
                .environmentObject(settings)
        }
    }
}

struct SettingsComponent: RealityKit.Component {
    var settings: Settings
}

class UnderwaterView: ARView {
    let settings: Settings
    private func addEntity(_ entity: Entity) {
        entity.components[SettingsComponent.self] =
            SettingsComponent(settings: self.settings)
    }
}

关键点:

  • Settings 作为 @StateObjectenvironmentObject 在 SwiftUI 中传递(12:36)
  • 包装为 SettingsComponent 后附加到 Entity
  • 自定义系统从 Entity 的组件中读取设置值

材质系统升级

RealityKit 2 新增了 PhysicallyBasedMaterial,与 USD 材质规范对齐,是 SimpleMaterial 的超集。

var faceMaterial = PhysicallyBasedMaterial()
faceMaterial.roughness = 0.1
faceMaterial.metallic = 1.0
faceMaterial.blending = .transparent(opacity: .init(scale: 1.0))

let sparklyNormalMap = try! TextureResource.load(named: "sparkly")
faceMaterial.normal.texture = PhysicallyBasedMaterial.Texture.init(sparklyNormalMap)

faceMaterial.baseColor.texture = PhysicallyBasedMaterial.Texture.init(faceTexture)
faceEntity.model!.materials = [faceMaterial]

关键点:

  • PhysicallyBasedMaterial 包含标准 PBR 属性:baseColor、roughness、metallic、normal、ambientOcclusion、clearcoat 等(13:57)
  • 支持透明度纹理和 opacityThreshold(14:35)
  • VideoMaterial 新增透明度支持(13:42)
  • CustomMaterial 允许用 Metal 代码编写自定义着色器(15:05)

动画增强

动画 API 新增了混合层(Blend Layers)和程序化动画。

// 动画过渡
entity.playAnimation(animation, transitionDuration: 0.3)

// 混合层:Walking 在上层,Idle 在下层
// 调整 blend factor 控制权重
// 改变 playback speed 控制速度

关键点:

  • transitionDuration 让新旧动画平滑过渡(15:55)
  • Blend Layers:多个动画在不同层播放,通过 blend factor 混合(16:22)
  • 改变 playback speed 让角色走快或走慢(16:47)
  • 用角色相对地面的速度控制 blend factor 和 speed,减少脚步滑动(16:55)
  • FromToByAnimation 程序化创建变换动画(18:33)
  • AnimationView 从 USD 时间轴切片出多个动画片段(17:47)

角色控制器

角色控制器让 Entity 与场景中的碰撞体进行物理交互。

// 创建胶囊体形状的角色控制器
let characterController = CharacterController(
    height: capsuleHeight,
    radius: capsuleRadius
)
entity.components[CharacterControllerComponent.self] =
    CharacterControllerComponent(characterController)

// 每帧调用,自动避开障碍物
characterController.move(to: targetPosition)

// 忽略障碍物,直接瞬移
characterController.teleport(to: targetPosition)

关键点:

  • 胶囊体形状匹配角色轮廓(19:55)
  • move(to:) 自动与环境网格(LiDAR 生成)碰撞检测(20:08)
  • teleport(to:) 忽略障碍物直接移动(20:19)
  • 演示中潜水员在沙发和地板间跳跃,自动与房间网格交互

运行时资源生成

面部网格

SceneUnderstanding 现在可以识别人脸并返回带 ModelComponent 的 Entity。

static let sceneUnderstandingQuery =
    EntityQuery(where: .has(SceneUnderstandingComponent.self) && .has(ModelComponent.self))

func findFaceEntity(scene: RealityKit.Scene) -> HasModel? {
    let faceEntity = scene.performQuery(sceneUnderstandingQuery).first {
        $0.components[SceneUnderstandingComponent.self]?.entityType == .face
    }
    return faceEntity as? HasModel
}

关键点:

  • SceneUnderstandingComponent.entityType 区分 .face.meshChunk(21:26)
  • 获取面部 Entity 后可以替换其材质
  • 演示中用 PencilKit 绘制图案,实时应用到面部网格

音频缓冲区

从任意 AVAudioBuffer 创建空间音频资源。

let synthesizer = AVSpeechSynthesizer()

func speakText(_ text: String, forEntity entity: Entity) {
    let utterance = AVSpeechUtterance(string: text)
    utterance.voice = AVSpeechSynthesisVoice(language: "en-IE")

    synthesizer.write(utterance) { audioBuffer in
        guard let audioResource = try? AudioBufferResource(
            buffer: audioBuffer,
            inputMode: .spatial,
            shouldLoop: true
        ) else { return }

        entity.playAudio(audioResource)
    }
}

关键点:

  • AudioBufferResourceAVAudioBuffer 创建(23:09)
  • inputMode: .spatial 启用 3D 定位音频
  • 其他模式:.nonSpatial.ambient
  • 可用 AVSpeechSynthesizer 将文字转为语音,或录制麦克风输入

核心启发

  1. 用 ECS 架构组织 AR 游戏逻辑:将行为拆分为独立的 System,状态放在 Component 中。Entity 只是标识符。这让代码更清晰,也便于多玩家同步。

  2. 角色控制器简化 AR 物理交互:不需要自己写碰撞检测和导航网格,角色控制器自动与 LiDAR 扫描的环境网格交互。

  3. 面部 AR 的新玩法:SceneUnderstanding 提供的人脸网格 + 自定义材质,可以实现虚拟妆容、面部滤镜、表情追踪等效果。

  4. 程序化音频生成AudioBufferResource 让 AR 中的音效不再依赖预置文件,可以实时合成、处理和应用音频。

  5. PBR 材质让虚拟内容更真实PhysicallyBasedMaterial 提供了完整的 PBR 工作流,配合 normal map、clearcoat 等高级属性,虚拟物体可以更好地融入真实环境光照。

关联 Session

评论

GitHub Issues · utterances