Concatenating transform animations in RealityKit
RealityKit 2023 transform animation is still imperfect today. However, you can sequentially merge several move(to:)
methods to go beyond 180 degree rotation barrier. Internally several rotation animations are merged into one smooth animation. I firmly believe that the reason for the 180 degree barrier
is some kind of RealityKit's quaternion limitation. This solution works in iOS and visionOS.
visionOS app version for Xcode 15 Simulator
.
import SwiftUI
import RealityKit
struct ContentView: View {
var body: some View {
RealityView { content in
let model = ModelEntity(mesh: .generateBox(size: 0.1))
content.add(model)
} update: { content in
if let model = content.entities.first {
// 540 degree CCW rotation in 4 seconds (about Z axis)
model.move(to: .init(roll: .pi), relativeTo: model,
duration: 4.0, timingFunction: .linear)
model.move(to: .init(roll: .pi), relativeTo: model,
duration: 4.0, timingFunction: .linear)
model.move(to: .init(roll: .pi), relativeTo: model,
duration: 4.0, timingFunction: .linear)
}
}
}
}
#Preview {
ContentView()
}
This post is also helpful.
SwiftUI animation for Model3D view
Also, you can prototype a scene in Reality Composer Pro app (do not forget to apply InputTarget
and Collision
components to 3D model) and then you'll be able to rotate a view with tap gesture using .rotation3DEffect(...)
modifier, where you can set a pivot (a.k.a. anchor) point.
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
@State private var rotation: Angle = .zero
var body: some View {
Model3D(named: "Scene", bundle: realityKitContentBundle)
.onTapGesture {
withAnimation(.smooth(duration: 0.5)) {
rotation.degrees -= 540
}
}
.rotation3DEffect(rotation, axis: .z, anchor: .center)
}
}
#Preview {
ContentView()
}