RealityKit Basics: Perform SwiftUI Animations
Starting in visionOS 26, we can perform SwiftUI animations in RealityKit.
Overview
SwiftUI has some pretty slick animation features that we can use across Apple platforms. Starting in visionOS 26, we can use these animation on our RealityKit entities. There are two main ways to do this.
Content animate
We can call content.animate in the make or update closure of RealityView. This is helpful when the animation is a side effect of something else happening in our app. For example, if we can to play an animation when a user changes a value.
content.animate {
let scaler: Float = subjectAToggle ? 2.0 : 1.0
subjectA.scale = .init(repeating: scaler)
}Let’s create a SwiftUI toggle toggle that will update the scale of an entity. We’ll add state and a binding to hold our animation. Then add a Toggle view that uses this binding.
fileprivate struct Example109ExampleA: View {
@State private var subjectA = Entity()
@State private var subjectAToggle = false
var subjectAToggleAnimation: Binding<Bool> {
$subjectAToggle.animation(.easeInOut(duration: 1))
}
var body: some View {
RealityView { content in
let subjectA = createStepDemoBox("subjectA", true)
self.subjectA = subjectA
content.add(subjectA)
} update: { content in
content.animate {
let scaler: Float = subjectAToggle ? 2.0 : 1.0
subjectA.scale = .init(repeating: scaler)
}
}
.toolbar {
ToolbarItem(placement: .bottomOrnament, content: {
Toggle(isOn: subjectAToggleAnimation, label: {
Text("Toggle Subject A")
})
})
}
}
}Entity animate
We can also call Entity.animate. This type method can be a bit easier to use. In this example, we’ll create an entity with a Tap Component that animates the scale change.
fileprivate struct Example109ExampleB: View {
// For this example, we'll use a state var. In a production app it makes more sense to keep entity state in components
@State private var subjectBToggle = false
var body: some View {
RealityView { content in
let subjectB = createStepDemoBox("subjectB", true)
content.add(subjectB)
let tap = TapGesture().onEnded({ [weak subjectB] _ in
// We'll use a SwiftUI animation to scale the entity
Entity.animate(.easeInOut(duration: 1), body: {
subjectBToggle.toggle()
let scaler: Float = subjectBToggle ? 2.0 : 1.0
subjectB?.scale = .init(repeating: scaler)
})
})
let gesture = GestureComponent(tap)
subjectB.components.set(gesture)
}
}
}I use this approach much more often than content.animate as it seems much more approachable. We can place animations like this in gesture and event closures. While Example B uses SwiftUI state to keep track of our toggle value, it may make more sense to store that in a component. If this value is only used for animation/internal RealityKit work, then save it on a custom component. On the other hand, if the animation needs to be a side effect of something else in the app, storing it in state or a model may be better.
See also:
- WWDC 2025 – Better together: SwiftUI and RealityKit
- Lab 061 – First look at SwiftUI animations in RealityKit
- Lab 062 – First look at Gesture Component
We can animate many properties on RealityKit components this way. But there are some complex values that well be tricky or impossible to animate with SwiftUI. In those cases we can use RealityKit animations or custom systems.

Example Code
struct Example109: View {
@State private var subjectA = Entity()
@State private var subjectAToggle = false
var subjectAToggleAnimation: Binding<Bool> {
$subjectAToggle.animation(.easeInOut(duration: 1))
}
@State private var subjectBToggle = false
var body: some View {
HStack() {
Example109ExampleA()
Example109ExampleB()
}
}
}
fileprivate struct Example109ExampleA: View {
@State private var subjectA = Entity()
@State private var subjectAToggle = false
var subjectAToggleAnimation: Binding<Bool> {
$subjectAToggle.animation(.easeInOut(duration: 1))
}
var body: some View {
RealityView { content in
let subjectA = createStepDemoBox("subjectA", true)
self.subjectA = subjectA
content.add(subjectA)
} update: { content in
content.animate {
let scaler: Float = subjectAToggle ? 2.0 : 1.0
subjectA.scale = .init(repeating: scaler)
}
}
.toolbar {
ToolbarItem(placement: .bottomOrnament, content: {
Toggle(isOn: subjectAToggleAnimation, label: {
Text("Toggle Subject A")
})
})
}
}
}
fileprivate struct Example109ExampleB: View {
// For this example, we'll use a state var. In a production app it makes more sense to keep entity state in components
@State private var subjectBToggle = false
var body: some View {
RealityView { content in
let subjectB = createStepDemoBox("subjectB", true)
content.add(subjectB)
let tap = TapGesture().onEnded({ [weak subjectB] _ in
// We'll use a SwiftUI animation to scale the entity
Entity.animate(.easeInOut(duration: 1), body: {
subjectBToggle.toggle()
let scaler: Float = subjectBToggle ? 2.0 : 1.0
subjectB?.scale = .init(repeating: scaler)
})
})
let gesture = GestureComponent(tap)
subjectB.components.set(gesture)
}
}
}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