You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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)
    }
}

关键说明

  1. 保留AnimationPlayer实例:播放动画时保存返回的AnimationPlayer,后续直接通过该实例修改速度,无需重新生成动画资源。
  2. 链式配置动画属性:使用repeat(_:)和speed(_:)方法直接修改原动画的配置,简化代码逻辑。
  3. 实时无中断调整:修改animationPlayer?.speed后,动画会立即以新速度继续当前周期运行,不会从头重启,也不会额外占用内存。

内容的提问来源于stack exchange,提问作者Ostoura

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:42:49