Swift - SCNAnimationPlayer setting duration cancels out timeOffset

107 Views Asked by At

I have an animation that I'm trying to start & end at specific places. I can set the start by setting the animationPlayer.animation.timeOffset, I'm also trying to set the animation to end about 20s after the timeOffset & I can do that by setting animationPlayer.animation.duration.

The problem that I'm facing is that setting the duration cancels out the timeOffset. If I use just .timeOffset I can get the animation to start from any position but as soon as duration is set the animation will play from the beginning.

The intended result would be this: The animation starts at 25s (timeOffset) runs for 20s (duration) & then loops back to the timeOffset.

let rootNode = sceneView.rootNode
    
    rootNode.enumerateChildNodes { child, _ in
        guard let animationPlayer = child.animationPlayer(forKey: key) else { return }
        animationPlayer.animation.timeOffset = 25
        animationPlayer.animation.duration = 20
        animationPlayer.animation.autoreverses = true
        animationPlayer.animation.isRemovedOnCompletion = false
    }
1

There are 1 best solutions below

0
Jon Willis On BEST ANSWER

The best solution I have found is something like this:

let player = model.animationPlayer(forKey: "all")
let animation = player?.animation
func restartAnimation(atTimeOffset timeOffset: TimeInterval, duration: TimeInterval) {
    animation?.timeOffset = timeOffset
    if isWalking {
        player?.play()
        let uuid = isWalkingUUID
        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            guard uuid == self.isWalkingUUID else { return }
            player?.stop(withBlendOutDuration: 0.2)
            restartAnimation(atTimeOffset: timeOffset, duration: duration)
        }
    } else {
        player?.stop(withBlendOutDuration: 0.2)
    }
}
restartAnimation(atTimeOffset: 33, duration: 0.6)