Looping an animation is possible by subscribing to the AnimationEvents.PlaybackCompleted event.
You'll have to move your animation logic into a separate function which you call once. Inside this function you subscribe to the PlaybackCompleted event. When this event is fired you call the same animation function.
You can subscribe to AnimationEvents by using the Scene.subscribe() method:
func subscribe<E>(to event: E.Type,
on sourceObject: EventSource? = nil,
_ handler: @escaping (E) -> Void) -> Cancellable where E : Event
Please note that you'll have to import the Combine framework to be able to use this:
import Combine
The animation function then looks like this:
// This needs to be an instance variable, otherwise it'll
// get deallocated immediately and the animation won't start.
var animUpdateSubscription: Cancellable?
func animate(entity: HasTransform,
angle: Float,
axis: SIMD3<Float>,
duration: TimeInterval,
loop: Bool)
{
var transform = entity.transform
// We'll add the rotation to the current rotation
transform.rotation *= simd_quatf(angle: angle, axis: axis)
entity.move(to: transform, relativeTo: entity.parent, duration: duration)
// Checks if we should loop and if we have already subscribed
// to the AnimationEvent. We only need to do this once.
guard loop,
animUpdateSubscription == nil
else { return }
animUpdateSubscription = scene.subscribe(to: AnimationEvents.PlaybackCompleted.self,
on: entity,
{ _ in
self.animate(entity: entity,
angle: angle,
axis: axis,
duration: duration,
loop: loop)
})
}
Now you can call this function once to trigger a looped animation:
animate(entity: entity,
angle: angle,
axis: axis,
duration: duration,
loop: loop)