I have a USDZ 3d model contains a running man animation and I manage to run the model well using this code:
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
// i could not add the definition to the animation resource back again
// so i generated a new one
let animRes = try! AnimationResource.generate(with: animationDefinition!)
manPlayer.playAnimation(animRes)
}
func increaseSpeed() {
speed += 0.1
animationDefinition?.speed = speed
// Now i wonder is this the best way to increase speed
// isn't it as if im adding more load to the memory
// by adding another players
let animRes = try! AnimationResource.generate(with: animationDefinition!)
manPlayer.playAnimation(animRes)
}
func decreaseSpeed() {
speed -= 0.1
animationDefinition?.speed = speed
// Now i wonder is this the best way to increase speed
// isn't it as if im adding more load to the memory
// by adding another players
let animRes = try! AnimationResource.generate(with: animationDefinition!)
manPlayer.playAnimation(animRes)
}
}
how to control speed of this animation while it is running without have to regenerate a resource and replay the animation over and over with every speed change knowing that every time the animation replayed it started from the frame zero meaning its not completing its cycle before its replayed but cut in the middle and start over again from start which I do not prefer to be happen.
The USDZ file is here if you wish to try https://www.worldhotelity.com/stack/run.usdz
Hi ostoura,
have you considered to use the AnimationPlaybackController returned by the playAnimation method?
Store the playbackController when initially play the animation
@State private var playbackController: AnimationPlaybackController?
Modify your playThis() to:
func playThis() {
guard let animationResource = manPlayer.availableAnimations.first else { return }
playbackController = manPlayer.playAnimation(animationResource.repeat(duration: .infinity), transitionDuration: 0.25, startsPaused: false) //infinity looping, smooth transition, animation starts immediately
playbackController?.speed = speed
}
Adjust speed functions
func increaseSpeed() {
speed += 0.1
playbackController?.speed = speed
}
func decreaseSpeed() {
speed = max(0.1, speed - 0.1) // prevent negative or zero speed
playbackController?.speed = speed
}
Now you should be able to adjust the animation speed while it is running
I hope this helps
Flip