探索 USDKit 以及 OpenUSD 的新进展
Discover USDKit and what’s new in OpenUSD
2026年6月10日
一句话判断
✅ Apple 终于用纯 Swift 重写了 USD 绑定(USDKit),让 3D 场景组装从“啃 C++ 头文件”变成了“写 SwiftUI 一样的日常”。
这场 Session 讲了什么
这场 Session 最值得关注的一件事,就是 Apple 终于把通用场景描述(Universal Scene Description, USD)从 C++ 的泥潭里拽了出来,给了 Swift 开发者一个原生的 USDKit。以前我们要在 Apple 平台上处理 USD,要么捏着鼻子用 C++ 桥接,要么依赖社区的 SwiftUSD。现在官方下场,不仅提供了原汁原味的 Swift API,还把 Mac 的“预览”App 变成了轻量级 3D 编辑器,甚至在 Safari 里加了 <model> 标签。这对做空间计算、电商 3D 展示或者数字孪生的团队来说,直接省掉了半年的基建时间。USD 不再是影视特效大佬的专属玩具,它正式成了 Apple 平台的一等公民。
值得深挖的点
USDKit 的 Composition(组合)机制与 Swift 化体验
Apple 推出 USDKit 的动机很明显:RealityKit 负责渲染和物理,但缺乏一个强大的场景图(Scene Graph)管理和资产组装工具。USD 的杀手锏是 Composition(组合),也就是通过引用(References)把多个 Layer(层)拼成一个 Stage(舞台),而不是把数据全塞进一个大文件。
在 C++ 里写 USD 组合代码非常繁琐,各种 SdfPath 和 UsdReferences 能让人看瞎眼。USDKit 把这些包装成了极其符合 Swift 直觉的 API。比如 scope.references.add("/assets/scope.usda"),一行代码就实现了资产引用。当上游美术修改了 scope.usda,你的 App 重新加载 Stage 时会自动拿到最新模型。
这里的 Trade-off 是,USDKit 目前看起来更偏向“场景组装和编辑”,而不是“底层自定义”。如果你需要写自定义的 USD Schema(模式),可能还是得回退到 C++ 或者等 Apple 后续开放更多底层 API。但对于 95% 只需要“把几个模型拼起来、调调位置、加点元数据”的 App 开发者来说,这个封装简直完美。
3D 资产瘦身与 Safari <model> 标签的降维打击
3D 内容上网页或进 App,最大的痛点就是体积。一个高精度的 USDZ 动辄几十 MB,用户加载时黄花菜都凉了。这次 Apple 联合开放媒体联盟(Alliance for Open Media)搞出了新的网格压缩(Mesh compression),配合现有的 AVIF 纹理压缩,能把资产体积平均缩小 7 倍,网格部分甚至能缩减 90%。
更狠的是 Safari 新增的 <model> 标签。以前在网页上展示 3D 模型,得引入 Three.js 或 Babylon.js,写一堆 WebGL 胶水代码。现在只要像写 <img> 一样写 <model src="car.usdz">,macOS 和 iOS 就能直接原生渲染,visionOS 还能让模型“破屏”跑到现实空间里。结合 exportPackage 里的 .preferSmallMeshFiles 选项,前端和客户端同学终于不用为了 3D assets 的体积和加载速度天天吵架了。
代码片段
1. 场景组装:打开 Stage 并引用外部资产
场景:在内存中打开一个主场景,检查有没有某个设备,没有的话通过引用(Reference)把外部资产轻量级地挂载进去,并调整位置。
import USDKit
// 打开磁盘上的主场景文件
let url = URL(fileURLWithPath: "/ALab/entry.usda")
let stage = try USDStage.open(url)
// 遍历场景树,找个叫 scope 的节点
var hasScope = false
for prim in stage.descendants {
if prim.name == "scope" {
hasScope = true
}
}
// 没找到?定义一个新的 Transform 节点并引用外部模型
if !hasScope {
let scope = stage.definePrim(at: "/World/scope", type: "Xform")
// 核心:不拷贝数据,只添加文件引用,上游更新这里自动同步
try scope.references.add("/ALab/assets/scope.usda")
// 添加平移操作并设置坐标,API 会自动处理 xformOpOrder
scope.addTransformOperation(type: .translate)
scope["xformOp:translate", as: USDValue.Vec3d.self] = [2.5, 0.0, -1.0]
}
坑:addTransformOperation 会自动帮你管理变换顺序(xformOpOrder),千万别自己手动去写 xformOpOrder 数组,容易和 API 内部状态冲突导致模型乱飞。
2. 空间无障碍:给 3D 物体打上 VoiceOver 标签
场景:为场景里的 3D 仪器添加辅助功能(Accessibility)标签和描述,让视障用户在使用 VoiceOver 探索空间时能听懂这是什么。
// 给节点应用 AccessibilityAPI 模式,实例名设为 "default"
try scope.applyAPISchema("AccessibilityAPI", instanceName: "default")
// 创建标签和描述的属性
scope.makeAttribute(named: "accessibility:default:label", as: .string)
scope.makeAttribute(named: "accessibility:default:description", as: .string)
// 填入具体的文案,Vision Pro 上的旁白会直接朗读这些内容
scope["accessibility:default:label", as: String.self] = "示波器"
scope["accessibility:default:description", as: String.self] =
"一台复古信号分析仪,带有 3D 线框显示屏,顶部有一个彩条测试监视器"
坑:USDKit 目前没有为所有 Schema 提供强类型的 Swift 属性包装,所以这里还得用字符串 Key(如 "accessibility:default:label")去读写。拼写错误编译器不会报错,建议把这些 Key 抽成常量。
3. 资产瘦身:导出极致压缩的 USDZ
场景:把编辑好的 Stage 导出为 USDZ 格式,同时开启纹理和网格压缩,大幅减小文件体积以便在网络上传输。
let output = URL(fileURLWithPath: "/ALab/alab_compressed.usdz")
// 导出 USDZ 包,开启双重压缩
try stage.exportPackage(
to: output,
options: [
// 使用 AVIF 压缩纹理,standard 质量在体积和画质间平衡最好
.preferSmallTextureFiles(quality: .standard),
// 开启网格几何体压缩,最高能减小 90% 体积
.preferSmallMeshFiles
]
)
坑:.preferSmallMeshFiles 会改变网格的拓扑数据结构,如果你的下游管线(比如某些老旧的第三方渲染器)不支持解压这种压缩网格,模型会加载失败。导出前务必在目标设备上验证。
最佳实践
老项目如果正在用 RealityKit 的 Entity.load 加载 USDZ,现在可以考虑把“场景组装”逻辑迁移到 USDKit。用 USDKit 在内存里把多个 USDZ 拼好、调好位置、加上元数据,然后再整体转给 RealityKit 渲染。这比在 RealityKit 里用代码手动算矩阵、挂 Entity 要优雅得多,而且美术可以直接在 Mac 的“预览”App 里看你拼好的 Scene。
新项目强烈建议直接拥抱 USD 标准,放弃自己发明 JSON 格式来描述 3D 场景。USDKit 的 USDStage 和 Composition 机制天生就是为了解决“多部门协同、大场景管理”而生的。
实战中最容易踩的坑是“层级路径(Path)硬编码”。在 USD 里,/World/scope 这样的路径是唯一的。如果两个美术给了同名的节点,或者你在代码里写死了路径,一旦上游资产结构微调,你的代码就会静默失败(找不到节点)。尽量用遍历(stage.descendants)配合自定义元数据(Metadata)来查找目标节点。
还有什么值得关注
- Gaussian Splats(高斯泼溅)原生支持:Apple 和 NVIDIA 等大厂在 OpenUSD 里加了
Particle Fields基础类型,现在你可以把 3D 高斯泼溅数据和传统多边形模型放在同一个 USD 场景里渲染了。 - Mac“预览”App 变身 3D 编辑器:macOS 27 的预览 App 不仅能看 USD,还能直接调灯光、改属性,甚至内置了基于物理的光线追踪(Raytracer)渲染器,美术同学可以直接用它做最终效果确认。
- Spatial Preview 跨端协同:新的 Spatial Preview 框架让 Mac 上的修改能实时同步到 Vision Pro 的 Quick Look 里,还支持 SharePlay,导演和美术可以戴着 headset 一起在虚拟空间里“指点江山”。