Work with Reality Composer Pro content in Xcode
Graphics & Games 进阶 20m

在 Xcode 中使用 Reality Composer Pro 内容

Work with Reality Composer Pro content in Xcode

2023年6月5日

在 Apple 官方观看视频

一句话判断

Reality Composer Pro 项目本质上是 Swift Package——你可以在里面创建自定义 Component、用 Shader Graph 制作材质、通过 RealityView 加载场景、用 Attachments API 在 3D 空间中放置 SwiftUI 视图,整个 ECS 架构与代码无缝衔接。

这场 Session 讲了什么

RealityKit 和 Reality Composer Pro 团队的 Amanda 介绍了如何在 Xcode 中加载和操作 Reality Composer Pro 创建的内容。

以优胜美地地形图为案例,Session 展示了完整的开发流程:在 Reality Composer Pro 中组装场景、创建自定义组件、在 Xcode 中加载场景并添加交互。

ECS 架构:Entity-Component-System 是 RealityKit 的核心架构。Entity 是场景中的任何物体(可见或不可见),Component 存储数据(可动态添加/移除),System 提供每帧执行的行为逻辑。这和面向对象的继承模型不同——Entity 的”性质”由其拥有的 Component 组合决定。

从 Reality Composer Pro 加载内容:使用 Entity 的异步初始化器,指定场景名称和 bundle。Reality Composer Pro 项目编译后产生 realityKitContentBundle,Xcode 自动生成这个常量。

自定义 Component:在 Reality Composer Pro 中创建自定义 Component,它会在 Xcode 中生成对应的 Swift 文件。你可以在其中添加属性(如兴趣点的名称和描述),然后在 Reality Composer Pro 的 Inspector 中填写这些属性的值。

RealityView:SwiftUI 的新视图类型,是连接 SwiftUI 和 RealityKit 的桥梁。在 make 闭包中加载实体,在 update 闭包中响应状态变化。

Attachments API:允许在 3D 场景中定位 SwiftUI 视图。比如在地图上方的兴趣点位置放置 2D 信息按钮。

Shader Graph 集成:在 Reality Composer Pro 中创建的 MaterialX 着色器可以在代码中通过 Component 动态控制参数。

值得深挖的点

Reality Composer Pro 项目是 Swift Package:这意味着你可以在同一个项目中同时编辑 3D 场景和 Swift 代码。自定义 Component 生成的 Swift 文件就在 Package 中,可以直接编辑。

场景加载的命名机制:Reality Composer Pro 中的每个标签页(tab)代表一个根实体,可以在运行时通过字符串名称加载。一个项目可以有多个场景——既可以作为完整场景加载,也可以作为可复用的组件(assemblage)加载。

Attachments 的 SwiftUI-3D 桥接:Attachments API 让你可以在 3D 空间的特定位置放置 SwiftUI 视图。位置由 Reality Composer Pro 中的实体位置决定,视图内容由 SwiftUI 代码决定。这是 2D UI 和 3D 场景交互的关键机制。

自定义 Component 的双向编辑:在 Reality Composer Pro 中创建 Component 的属性结构,在 Xcode 中编写属性逻辑,再回到 Reality Composer Pro 中填写属性值。这个往返工作流非常流畅。

代码片段

// 从 Reality Composer Pro 加载场景
RealityView { content in
    let entity = try await Entity(
        named: "DioramaAssembled",
        in: realityKitContentBundle
    )
    content.add(entity)
}
// 自定义 Component - 在 Reality Composer Pro 中创建
// 自动生成 Swift 文件 PointOfInterestComponent.swift
struct PointOfInterestComponent: Component {
    var name: String = ""
    var description: String = ""

    // 可以添加计算属性和方法
    var displayName: String {
        name.replacingOccurrences(of: "_", with: " ")
    }
}
// RealityView + Attachments - 在 3D 空间中放置 SwiftUI 视图
RealityView { content in
    let scene = try await Entity(named: "DioramaAssembled",
                                  in: realityKitContentBundle)
    content.add(scene)
} attachments: {
    // 为每个兴趣点创建 SwiftUI 按钮
    ForEach(pointsOfInterest) { poi in
        Attachment(id: poi.name) {
            Button(action: { showDetail(poi) }) {
                VStack {
                    Image(systemName: "info.circle")
                    Text(poi.displayName)
                        .font(.caption)
                }
            }
        }
    }
}
// 查找特定实体并读取自定义 Component
let entity = scene.findEntity(named: "Ribbon_Beach")
if let poiComponent = entity?.components[PointOfInterestComponent.self] {
    print("兴趣点: \(poiComponent.name)")
    print("描述: \(poiComponent.description)")
}

// 动态修改 Component
entity?.components.set(PointOfInterestComponent(
    name: "Ribbon Beach",
    description: "Catalina Island 的美丽海滩"
))
// 控制 Shader Graph 材质参数
// 在 Reality Composer Pro 中创建的材质参数
// 可以通过 ShaderGraphMaterial 在代码中修改
if let component = entity.components[ShaderGraphMaterial.self] {
    var material = component
    try material.setParameter(name: "MorphAmount", value: Float(0.5))
    entity.components.set(material)
}

最佳实践

  • USD 资产放入 .rkassets 目录:Xcode 会将 .rkassets 编译为运行时更快加载的格式。不要直接使用裸 USD 文件。
  • 用命名实体定位关键元素:在 Reality Composer Pro 中为需要在代码中访问的实体命名,运行时用 findEntity(named:) 查找。
  • 自定义 Component 在 Reality Composer Pro 中创建:而不是纯代码创建。这样视觉编辑和代码编辑可以并行工作。
  • Attachments 用于 2D-3D 混合 UI:在 3D 场景上方浮动的信息卡片、标签和按钮用 Attachments API,不要尝试用纯 RealityKit 实现。
  • 用 System 处理每帧逻辑:需要持续更新的行为(如动画、物理模拟)放在 ECS 的 System 中,而不是 SwiftUI 的视图更新中。

还有什么值得关注

  • RealityView 是 SwiftUI 和 RealityKit 之间的官方桥梁,使用它而不是 UIViewRepresentable 桥接。
  • .rkassets 是编译优化后的格式,直接使用 USD 文件会明显更慢。
  • Session 展示了一个地形图在优胜美地和 Catalina Island 之间变形的效果,这个 morph 动画通过 Shader Graph 的参数驱动。
  • Reality Composer Pro 的 Component 编辑器和 Xcode 的 Swift 代码编辑器之间的双向同步是整个工作流的核心。
WWDC 2023