visionOS 开发 / 使用 RealityKit 播放动画(二)
了解如何使用 RealityKit 在 3D 模型上播放动画。
在上一篇文章中,我们已经了解了如何使用 RealityKit 播放 USDZ 模型的内置动画。本文将介绍如何为模型添加自定义的空间移动动画。
添加空间移动动画
你也可以使用 RealityKit 定义自定义动画,所有动画的本质都是对 modelEntity.transform 属性的修改/更新,包括:
translation
(位置)scale
(缩放)-
rotation
(旋转)
RealityKit 提供了两种为 Entity 对象添加空间移动动画的方式。对于简单的变换,可以使用 Entity 自带的基本方法。而对于高自定义、复杂的动画,可以使用 AnimationResource 来实现。
基本方法
常见的基本方法包括 move
、look(at:)
、scale(to:)
、rotate(by:)
- 适用于快速实现简单变换的场景。
- 当需要单一的变换(位置、旋转、缩放)时,使用这些方法更方便。
例如,使用.move 方法来实现 3D 模型的移动,我们首先需要声明一个 transform
变量,并将 Entity
对象的 transform
属性赋值给它。这样可以确保在后续修改时,除了被修改的变量外,其他属性保持不变。
以下代码实现让 robot 模型沿 Z 轴方向移动 5 米:
// 更新模型位置的变换
var transform = robot.transform
transform.translation = [0.0, 0.0, 5.0] // 目标位置
// 使用 DispatchQueue.main.async 确保在主线程上执行
DispatchQueue.main.async {
print("Moving robot to position: \(transform.translation)")
if let parent = robot.parent {
robot.move(to: transform, relativeTo: nil, duration: 25.0)
} else {
robot.move(to: transform, relativeTo: nil, duration: 25.0)
}
}
除了对 transform.translation
属性进行控制,我们还能同时控制 transform.scale
和 transform.rotation
属性。
通过调整,robot 模型将在 25 秒内平滑地移动到目标位置 [0.0, 0.0, 5.0]
,并同时放大到 2 倍,并沿着 Y 轴旋转方向:
/ 更新模型位置的变换
var transform = robot.transform
transform.translation = [0.0, 0.0, 5.0] // 目标位置
transform.rotation = simd_quatf(angle: .pi, axis: [0, 1, 0])
transform.scale = [10.0, 10.0, 10.0] // 目标缩放
// 使用 DispatchQueue.main.async 确保在主线程上执行
DispatchQueue.main.async {
print("Moving robot to position: \(transform.translation)")
if let parent = robot.parent {
robot.move(to: transform, relativeTo: nil, duration: 25.0)
} else {
robot.move(to: transform, relativeTo: nil, duration: 25.0)
}
}
look(at:)
、scale(to:)
、rotate(by:)
也可以方便的实现基础动画效果,我们在下一篇文章中再详细介绍使用方法。
AnimationResource
RealityKit 提供了多种动画类型,包括 FromToByAnimation
、BlendTreeAnimation
、OrbitAnimation
和 SampledAnimation
。
- 适用于需要复杂动画效果的场景。
- 当需要组合多个动画或创建复杂动画序列时,使用这些动画资源可以提供更多的控制和灵活性。
FromToByAnimation
是一种动画类型,而 AnimationResource
是一种用来管理和播放这些动画的资源。要使用这些动画类型,通常需要创建动画定义,然后生成 AnimationResource
,再将其应用到实体上。
下面这段代码,通过 FromToByAnimation 实现和 .move 方法相同的效果:
// 更新模型位置的变换
let initialTransform = robot.transform
var targetTransform = initialTransform
transform.translation = [0.0, 0.0, 5.0] // 目标位置
transform.rotation = simd_quatf(angle: .pi, axis: [0, 1, 0])
transform.scale = [10.0, 10.0, 10.0] // 目标缩放
// 定义 FromToByAnimation 动画
let animationDefinition = FromToByAnimation(
to: targetTransform,
duration: 25,
bindTarget: .transform
)
// 生成 AnimationResource 并播放
let animationResource = try AnimationResource.generate(with: animationDefinition)
// 播放动画
robot.playAnimation(animationResource)
AnimationResource
的一个主要优势在于它的复用性。一旦创建了一个动画资源,可以将其应用到多个模型上,而不需要为每个模型单独定义动画。这使得动画的管理和应用更加高效和灵活。
如果我加载了另一个 car 实体,我也可以直接将 animationResource
应用到该模型上:
// 更新模型位置的变换
let initialTransform = robot.transform
var targetTransform = initialTransform
transform.translation = [0.0, 0.0, 5.0] // 目标位置
transform.rotation = simd_quatf(angle: .pi, axis: [0, 1, 0])
transform.scale = [10.0, 10.0, 10.0] // 目标缩放
// 定义 FromToByAnimation 动画
let animationDefinition = FromToByAnimation(
to: targetTransform,
duration: 25,
bindTarget: .transform
)
// 生成 AnimationResource 并播放
let animationResource = try AnimationResource.generate(with: animationDefinition)
// 播放动画
robot.playAnimation(animationResource)
car.transform.translation = [-0.5, 0, 0]
car.playAnimation(animationResource)
灵活运用 FromToByAnimation
方法,可以创建更复杂、有趣的动画效果。通过学习 FromToByAnimation
和 .move()
方法,你已经掌握了如何使用实体自带的基本方法以及更高阶的 AnimationResource
来为 3D 模型添加动画效果。
在下一篇文章中,我将更详细介绍 RealityKit 提供的其他基本方法和动画类型,例如 look(at:)
、OrbitAnimation
和 SampledAnimation
。
使用 RealityKit,你可以轻松地播放内置动画或定义自定义动画,以创建动态和引人入胜的增强现实体验。