RealityKit Basics: Exploring SwiftUI Animations
Selecting from a short list of animations. Animating several RealityKit values.
Overview
We already learned how to Perform SwiftUI Animations in RealityKit. Now let’s look at some of the options we have. This post covers two concepts.
- Animating properties from various RealityKit components
- Selecting SwiftUI animations
Animating Components
As we saw in the last post, not all components and values can be animated. Apple shared a list in their WWDC session WWDC 2025 – Better together: SwiftUI and RealityKit

Let’s take a look at three examples. We’ll keep it simple and animate based a boolean value. The content.animate block is triggered anytime we change the value of subjectAToggle.
- Animate part of the transform for the entity, scale in this case
- Animate the base color of a material
- Animate the angles for a spotlight
RealityView { content in
...
} update: { content in
content.animate {
// Animate part of the transfrm
let scaler: Float = subjectAToggle ? 2.0 : 1.0
subjectA.scale = .init(repeating: scaler)
// Animate a material value
if var material = subjectA.components[ModelComponent.self]?.materials.first as? PhysicallyBasedMaterial {
material.baseColor.tint = UIColor(subjectAToggle ? .stepRed : .stepGreen)
subjectA.components[ModelComponent.self]?.materials[0] = material
}
// Animate a light value
if let spotLightEntity = subjectA.findEntity(named: "SpotLight") {
spotLightEntity.components[SpotLightComponent.self]?.innerAngleInDegrees = subjectAToggle ? 45.0 : 15.0
spotLightEntity.components[SpotLightComponent.self]?.innerAngleInDegrees = subjectAToggle ? 60.0 : 20.0
}
}
}
Selecting Animations
Exactly how the components are animated depends on on the animation that we provide to subjectAToggleAnimation binding.
var selectedAnimation: Animation { selectedAnim.animation }
var subjectAToggleAnimation: Binding<Bool> {
$subjectAToggle.animation(selectedAnimation)
}Let’s mock up a few from the presets
enum AnimChoice {
case easeInOut
case smooth
case snappy
case bouncy
case bouncyExtra
case springBounce
var animation: Animation {
switch self {
case .easeInOut:
return .easeInOut(duration: 1)
case .springBounce:
return .spring(.bouncy(duration: 2.0, extraBounce: 0.1), blendDuration: 0.2)
case .smooth:
return .smooth
case .snappy:
return .snappy
case .bouncy:
return .bouncy
case .bouncyExtra:
return .bouncy(duration: 1.0, extraBounce: 0.1)
}
}
}We can use this to set the type of animation we want to test, then toggle the value. Check out the video for a quick demo of each animation.
Spend some time with these animations. Many of them have duration or other values you can provide to tailor them to your needs.
Full Example Code
struct Example110: View {
@State private var subjectA = Entity()
@State private var subjectAToggle = false
enum AnimChoice {
case easeInOut
case smooth
case snappy
case bouncy
case bouncyExtra
case springBounce
var animation: Animation {
switch self {
case .easeInOut:
return .easeInOut(duration: 1)
case .smooth:
return .smooth
case .snappy:
return .snappy
case .bouncy:
return .bouncy
case .bouncyExtra:
return .bouncy(duration: 1.0, extraBounce: 0.1)
case .springBounce:
return .spring(.bouncy(duration: 2.0, extraBounce: 0.1), blendDuration: 0.2)
}
}
}
@State private var selectedAnim: AnimChoice = .easeInOut
var selectedAnimation: Animation { selectedAnim.animation }
var subjectAToggleAnimation: Binding<Bool> {
$subjectAToggle.animation(selectedAnimation)
}
var body: some View {
RealityView { content in
guard let scene = try? await Entity(named: "AnimatedComponents", in: realityKitContentBundle) else { return }
scene.position.y = -0.4
content.add(scene)
guard let subjectA = scene.findEntity(named: "SubjectA") else { return }
self.subjectA = subjectA
} update: { content in
content.animate {
// Animate part of the transfrm
let scaler: Float = subjectAToggle ? 2.0 : 1.0
subjectA.scale = .init(repeating: scaler)
// Animate a material value
if var material = subjectA.components[ModelComponent.self]?.materials.first as? PhysicallyBasedMaterial {
material.baseColor.tint = UIColor(subjectAToggle ? .stepRed : .stepGreen)
subjectA.components[ModelComponent.self]?.materials[0] = material
}
// Animate a light value
if let spotLightEntity = subjectA.findEntity(named: "SpotLight") {
spotLightEntity.components[SpotLightComponent.self]?.innerAngleInDegrees = subjectAToggle ? 45.0 : 15.0
spotLightEntity.components[SpotLightComponent.self]?.innerAngleInDegrees = subjectAToggle ? 60.0 : 20.0
}
}
}
.ornament(attachmentAnchor: .scene(.trailing), ornament: {
VStack(alignment: .leading, spacing: 8) {
Button(action: { selectedAnim = .easeInOut }) {
Label("EaseInOut", systemImage: selectedAnim == .easeInOut ? "checkmark.circle.fill" : "circle")
.frame(maxWidth: .infinity, alignment: .leading)
}
Button(action: { selectedAnim = .springBounce }) {
Label("Spring", systemImage: selectedAnim == .springBounce ? "checkmark.circle.fill" : "circle")
.frame(maxWidth: .infinity, alignment: .leading)
}
Button(action: { selectedAnim = .smooth }) {
Label("Smooth", systemImage: selectedAnim == .smooth ? "checkmark.circle.fill" : "circle")
.frame(maxWidth: .infinity, alignment: .leading)
}
Button(action: { selectedAnim = .snappy }) {
Label("Snappy", systemImage: selectedAnim == .snappy ? "checkmark.circle.fill" : "circle")
.frame(maxWidth: .infinity, alignment: .leading)
}
Button(action: { selectedAnim = .bouncy }) {
Label("Bouncy", systemImage: selectedAnim == .bouncy ? "checkmark.circle.fill" : "circle")
.frame(maxWidth: .infinity, alignment: .leading)
}
Button(action: { selectedAnim = .bouncyExtra }) {
Label("Bouncy+ ", systemImage: selectedAnim == .bouncyExtra ? "checkmark.circle.fill" : "circle")
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.frame(width: 160)
.padding()
.glassBackgroundEffect()
// Yep, ornament on an ornament. What are you going to do? Call the ornament police?
.ornament(attachmentAnchor: .parent(.top), contentAlignment: .bottom, ornament: {
HStack {
Toggle(isOn: subjectAToggleAnimation, label: {
Text("Toggle")
})
.toggleStyle(.button)
.padding()
}
.glassBackgroundEffect()
})
})
}
}
Support our work so we can continue to bring you new examples and articles.
Download the Xcode project with this and many more examples from Step Into Vision.
Some examples are provided as standalone Xcode projects. You can find those here.

Follow Step Into Vision