swiftarkitrealitykit

Animate rotation of an Entity


I am fairly new to the ARKit / RealityKit and I want to animate the rotation of a loaded USDZ model. Unfortunately, I can't get it to work.

guard let modelEntity = try? Entity.loadModel(named: "toy_biplane_idle") else {
      return
}
anchorEntity.addChild(modelEntity)
var rotationTransform: Transform = Transform()
rotationTransform.rotation = .init(angle: 30 * .pi / 180, axis: .init(x: 1, y: 1, z: 1))
// modelEntity.orientation = rotationTransform.rotation // this works but is not animated
modelEntity.move(to: rotationTransform, relativeTo: modelEntity.parent, duration: 1.0) // no effect at all

I tried to use the move(to: method with a duration but it has no effect at all, there is neither animation nor any rotation. What am I doing wrong ?


Solution

  • First Approach | .move(..) method

    In iOS, you have to apply the move(..) method after appending the biplane model to the scene:

    import SwiftUI
    import RealityKit
    
    struct ContentView : View {
        var body: some View {
            ARBiplaneView()
                .ignoresSafeArea()
        }
    }
    struct ARBiplaneView : UIViewRepresentable {
        let arView = ARView(frame: .zero)
        let anchor = AnchorEntity()
        
        func makeUIView(context: Context) -> ARView {
            let modelEntity = try! Entity.loadModel(named: "toy_biplane_idle")
            modelEntity.scale *= 4
            anchor.addChild(modelEntity)
        
            var transform: Transform = Transform()
            transform.translation.z = -2.0
            transform.rotation = .init(angle: .pi/2, axis: [0,1,0])
            
            // doesn't work here
            // modelEntity.move(to: transform, relativeTo: modelEntity, duration: 5.0)
    
            arView.scene.anchors.append(anchor)
            
            // DOES WORK HERE
            modelEntity.move(to: transform, relativeTo: modelEntity, duration: 5.0)
            
            return arView
        }
        func updateUIView(_ view: ARView, context: Context) { }
    }
    

    Second Approach | FromToByAnimation value

    The only disappointment when using this approach is that repeatMode pty doesn't work in Xcode 16. I hope this feature will be fixed soon.

    func makeUIView(context: Context) -> ARView {
        model.scale *= 4
        model.transform.rotation = simd_quatf(angle: .pi, axis: [0, 1, 0])
        let transform = model.transform
        
        model.transform.rotation *= simd_quatf(angle: -.pi, axis: [0, 1, 0])
        let definition = FromToByAnimation(to: transform, duration: 2, bindTarget: .transform, repeatMode: .none)
        let animationView = AnimationView(source: definition)
        if let resource = try? AnimationResource.generate(with: animationView) {
            // model.playAnimation(resource.repeat())
            model.playAnimation(resource)
        }
        anchor.addChild(model)
        arView.scene.anchors.append(anchor)
        return arView
    }