如何在RealityView中调整运行中USDZ动画的播放速度
动态调整RealityKit中USDZ动画速度(无需重启动画)
问题背景
我有一个包含跑步小人动画的USDZ 3D模型,通过代码实现了播放,但调整速度时每次都要重新生成AnimationResource并重播动画,导致动画中途从头开始,无法完成当前周期。希望找到无需重播、可在动画运行过程中直接调整速度的方法。
原实现代码:
import SwiftUI import RealityKit struct ContentView: View { @State var animationResource: AnimationResource? @State var animationDefinition: AnimationDefinition? @State var manPlayer = Entity() @State var speed:Float = 0.5 var body: some View { VStack { RealityView { content in if let item = try? await Entity(named: "run.usdz") { manPlayer = item content.add(manPlayer) } } HStack { Button(action: playThis) { Text("Play") } Button(action: increaseSpeed) { Text("increase Speed (+) ") } Button(action: decreaseSpeed) { Text("decrease Speed (-) ") } } } } func playThis() { animationResource = manPlayer.availableAnimations[0] animationDefinition = animationResource?.definition animationDefinition?.repeatMode = .repeat animationDefinition?.speed = speed let animRes = try! AnimationResource.generate(with: animationDefinition!) manPlayer.playAnimation(animRes) } func increaseSpeed() { speed += 0.1 animationDefinition?.speed = speed let animRes = try! AnimationResource.generate(with: animationDefinition!) manPlayer.playAnimation(animRes) } func decreaseSpeed() { speed -= 0.1 animationDefinition?.speed = speed let animRes = try! AnimationResource.generate(with: animationDefinition!) manPlayer.playAnimation(animRes) } }
解决方案
核心思路是利用AnimationPlayer实例直接控制动画,替代每次重新生成AnimationResource的方式。playAnimation方法会返回一个AnimationPlayer,修改这个播放器的speed属性即可实时调整动画速度,且不会中断当前动画周期。
修改后的完整代码:
import SwiftUI import RealityKit struct ContentView: View { @State private var animationPlayer: AnimationPlayer? @State private var manEntity = Entity() @State private var speed: Float = 0.5 var body: some View { VStack { RealityView { content in if let item = try? await Entity(named: "run.usdz") { manEntity = item content.add(manEntity) } } HStack(spacing: 20) { Button("Play") { playAnimation() } Button("Speed +") { speed += 0.1 animationPlayer?.speed = speed } Button("Speed -") { speed = max(0.1, speed - 0.1) // 避免速度降至0以下导致动画停滞 animationPlayer?.speed = speed } } .padding() } } private func playAnimation() { guard let animation = manEntity.availableAnimations.first else { return } // 链式配置动画的重复模式与初始速度 let modifiedAnimation = animation.repeat(.repeat).speed(speed) // 播放动画并保存播放器实例,用于后续速度调整 animationPlayer = manEntity.playAnimation(modifiedAnimation) } }
关键说明
- 保留AnimationPlayer实例:播放动画时保存返回的
AnimationPlayer,后续直接通过该实例修改速度,无需重新生成动画资源。 - 链式配置动画属性:使用
repeat(_:)和speed(_:)方法直接修改原动画的配置,简化代码逻辑。 - 实时无中断调整:修改
animationPlayer?.speed后,动画会立即以新速度继续当前周期运行,不会从头重启,也不会额外占用内存。
内容的提问来源于stack exchange,提问作者Ostoura
相关产品推荐
相关产品推荐

