深入 RealityKit 2
Dive into RealityKit 2
2021年6月10日
一句话判断
RealityKit 2 终于不是玩具了 —— 自定义材质、程序化网格生成、角色动画系统这三个功能补齐之后,Unity 开发者总算有理由认真看一眼这个框架了。
这场 Session 讲了什么
RealityKit 2 是一次重大的功能扩展,把 RealityKit 从一个”只能加载 USDZ 模型并放在平面上”的简单框架,提升到了可以构建完整 AR 应用的水平。
核心更新包括:自定义材质系统(Custom Material),开发者可以编写 Metal shader 来控制渲染效果;程序化网格生成(MeshDescriptor),用代码创建几何体而不依赖预制的 3D 模型文件;角色动画(Animation Library)的增强,支持动画混合、动画事件回调和程序化动画。此外还有物理模拟的改进、空间音频的集成、以及对 Entity Component System(ECS)架构的更多控制。
Session 用一个示例 AR 游戏贯穿全程,展示了如何用新 API 构建一个有碰撞检测、自定义视觉效果和音效的交互体验。
值得深挖的点
Custom Material 的 shader 架构。RealityKit 2 的 CustomMaterial 允许你写 Surface Shader 和 Geometry Modifier。Surface Shader 控制每个像素的颜色输出,Geometry Modifier 可以在 GPU 端修改顶点位置(比如做波浪变形)。这和 Unity 的 Shader Graph 概念类似,但你需要直接写 Metal 代码,没有可视化编辑器。shader 代码通过 CustomMaterial 的 surfaceShader 属性注入,支持传递自定义参数。
MeshDescriptor 的程序化建模。MeshDescriptor 让你用代码定义顶点、法线、纹理坐标和索引,直接生成 MeshResource。这对需要动态生成几何体的场景(如数据可视化、动态地形)非常有用。性能方面,MeshResource 可以在后台线程生成,不会阻塞渲染。但生成的网格不支持实时修改顶点(不支持 morph target),要变形还是得依赖 Geometry Modifier shader。
代码片段
程序化创建网格:
import RealityKit
func createCustomMesh() -> ModelEntity {
// 创建一个简单的立方体网格
var descriptor = MeshDescriptor()
let halfSize: Float = 0.05
// 定义立方体的 8 个顶点
let positions: [SIMD3<Float>] = [
[-halfSize, -halfSize, -halfSize],
[ halfSize, -halfSize, -halfSize],
[ halfSize, halfSize, -halfSize],
[-halfSize, halfSize, -halfSize],
[-halfSize, -halfSize, halfSize],
[ halfSize, -halfSize, halfSize],
[ halfSize, halfSize, halfSize],
[-halfSize, halfSize, halfSize],
]
descriptor.positions = MeshBuffer(positions)
// 定义三角面片索引(6 个面,每个面 2 个三角形)
descriptor.primitives = .triangles([
0,1,2, 0,2,3, // 前
4,6,5, 4,7,6, // 后
// ... 其他面
])
let meshResource = try! MeshResource.generate(from: [descriptor])
let material = SimpleMaterial(color: .blue, isMetallic: true)
return ModelEntity(mesh: meshResource, materials: [material])
}
使用自定义材质和 Shader:
import RealityKit
func createCustomMaterial() -> CustomMaterial {
// 加载 Metal shader 函数
let surfaceShader = CustomMaterial.SurfaceShader(
name: "hologramSurface",
library: try! CustomMaterial.DefaultLibrary()
)
var material = CustomMaterial(
surfaceShader: surfaceShader,
lightingModel: .lit
)
// 传递自定义参数给 shader
material.customParameter = SIMD4<Float>(0.5, 0.8, 1.0, 1.0)
return material
}
动画播放和混合:
import RealityKit
func playAnimation(on entity: Entity) {
// 加载带动画的模型
guard let animation = entity.availableAnimations.first else { return }
// 创建循环播放的动画
let loopingAnimation = animation.repeat(duration: .infinity)
// 播放动画并持有控制器引用
let controller = entity.playAnimation(loopingAnimation)
// 在 2 秒后淡出停止
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
controller.stop()
}
}
最佳实践
- Custom Material 的 shader 尽量保持简单。RealityKit 不像 Unity 有完整的 shader 调试工具,shader 编译错误只会在运行时出现。先在 Xcode 的 Metal shader playground 中验证逻辑,再搬到 RealityKit。
- 程序化网格适合静态几何体,动态内容还是用 Entity 层的 transform 动画。MeshResource 生成后不支持顶点级别的实时修改,需要形变效果请用 Geometry Modifier。
- 动画混合用
tryAnimation的blend方法。RealityKit 2 支持多个动画之间的平滑过渡,设置合适的 blend duration(建议 0.3 秒),避免动画跳变。
还有什么值得关注
- RealityKit 2 的
PhysicsBodyComponent支持了更多物理形状(Convex、Decomposed),碰撞检测更精确。 AudioComponent现在支持空间音频(Spatial Audio),声音会根据 Entity 和摄像头的相对位置自动调整。SynchronizationComponent让 Entity 状态可以通过 MultipeerConnectivity 自动同步,简化多人 AR 开发。