<!--
{
  "documentType" : "article",
  "framework" : "RealityKit",
  "identifier" : "/documentation/RealityKit/automatically-animating-realitykit-entities",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Automatically animating RealityKit entities"
}
-->

# Automatically animating RealityKit entities

Invoke implicit animations by setting the entity’s desired end state.

## Overview

When you build 3D experiences with RealityKit, you often animate changes to an entity’s position, rotation, scale, or other properties. You can animate entity properties explicitly by creating an [`AnimationResource`](/documentation/RealityKit/AnimationResource). RealityKit can also animate changes automatically using *implicit animations*, which let you describe only the desired end state inside a closure.

RealityKit offers two closure-based approaches to implicit animation:

- [`animate(_:body:completion:)`](/documentation/RealityKit/Entity/animate(_:body:completion:)): A type method you call directly on [`Entity`](/documentation/RealityKit/Entity). You pass in an <doc://com.apple.documentation/documentation/SwiftUI/Animation>, and RealityKit animates any property changes you make inside the `body` closure. Use this approach when your animation doesn’t depend on SwiftUI state.
- [`animate(body:completion:)`](/documentation/RealityKit/RealityViewContent/animate(body:completion:)): An instance method on the `content` parameter inside a [`RealityView`](/documentation/RealityKit/RealityView) update closure. This approach picks up the animation from the current SwiftUI transaction. You control the animation by binding it to the <doc://com.apple.documentation/documentation/SwiftUI/State> variable that triggers the update.

Both approaches can animate properties for the following component types:

- [`Transform`](/documentation/RealityKit/Transform)
- [`OpacityComponent`](/documentation/RealityKit/OpacityComponent)
- [`ModelComponent`](/documentation/RealityKit/ModelComponent)
- [`ParticleEmitterComponent`](/documentation/RealityKit/ParticleEmitterComponent)
- [`BillboardComponent`](/documentation/RealityKit/BillboardComponent)
- [`DirectionalLightComponent`](/documentation/RealityKit/DirectionalLightComponent)
- [`PointLightComponent`](/documentation/RealityKit/PointLightComponent)
- [`SpotLightComponent`](/documentation/RealityKit/SpotLightComponent)

## Animate entities without SwiftUI state

Use [`animate(_:body:completion:)`](/documentation/RealityKit/Entity/animate(_:body:completion:)) to animate entity properties without any SwiftUI state binding. Pass an <doc://com.apple.documentation/documentation/SwiftUI/Animation> value and a closure that sets the properties you want to change. RealityKit interpolates each property from its current value to the new one using the animation you specify. Often, you can get the animation you want by using one of the static type classes on <doc://com.apple.documentation/documentation/SwiftUI/Animation>, like <doc://com.apple.documentation/documentation/SwiftUI/Animation/linear> or <doc://com.apple.documentation/documentation/SwiftUI/Animation/easeOut>, rather than manually building a custom <doc://com.apple.documentation/documentation/SwiftUI/Animation>.

The following example moves an entity to a new position over one second using a `linear` animation to give a consistent speed throughout:

```swift
Entity.animate(.linear(duration: 1.0)) {
    entity.position = SIMD3<Float>(0, 1.5, -2)
}
```

The [`animate(_:body:completion:)`](/documentation/RealityKit/Entity/animate(_:body:completion:)) method works without a [`RealityView`](/documentation/RealityKit/RealityView) update closure or a SwiftUI state binding.

## Animate entities in a RealityView update closure

Use [`animate(body:completion:)`](/documentation/RealityKit/RealityViewContent/animate(body:completion:)) inside a [`RealityView`](/documentation/RealityKit/RealityView) update closure to animate entity changes in response to SwiftUI state changes. Because this method derives its animation from the current SwiftUI transaction, attach an animation to the <doc://com.apple.documentation/documentation/SwiftUI/State> variable that triggers the update.

Bind the animation to your state variable using the <doc://com.apple.documentation/documentation/SwiftUI/Binding/animation(_:)> modifier on a <doc://com.apple.documentation/documentation/SwiftUI/Binding>.

```swift
@State private var isScaled = false

var body: some View {
    VStack {
        RealityView { content in
            // Add entities during initial setup.
        } update: { content in
            guard let entity = content.entities.first else { return }

            content.animate {
                if isScaled {
                    entity.components[Transform.self]?.scale = SIMD3<Float>(repeating: 2)
                } else {
                    entity.components[Transform.self]?.scale = SIMD3<Float>(repeating: 1)
                }
            }
        }

        Toggle("Scale", isOn: $isScaled.animation(.linear(duration: 1.0)))
    }
}
```

The `.animation(.linear(duration: 1.0))` modifier on `$isScaled` attaches an animation to the binding. When `isScaled` changes, [`RealityView`](/documentation/RealityKit/RealityView) calls the update closure within a transaction that carries this animation. The [`animate(body:completion:)`](/documentation/RealityKit/RealityViewContent/animate(body:completion:)) call applies that animation to the property changes inside the closure.

> Important: Call ``doc://com.apple.RealityKit/documentation/RealityKit/RealityViewContent/animate(body:completion:)`` only inside the update closure, not the make closure. The method relies on a SwiftUI transaction, which is only available during an update pass. Calling it during initial setup has no effect and logs a fault.

## Animate multiple properties

You can change multiple properties inside a single `animate` closure. RealityKit creates a separate animation for each property and drives them all with the same timing.

The following example animates an entity’s position, scale, and opacity at the same time:

```swift
Entity.animate(.easeInOut(duration: 1.5)) {
    entity.components[Transform.self]?.translation = SIMD3<Float>(0, 2, -3)
    entity.components[Transform.self]?.scale = SIMD3<Float>(repeating: 1.5)
    entity.components[OpacityComponent.self]?.opacity = 0.5
}
```

> Important: When you animate ``doc://com.apple.RealityKit/documentation/RealityKit/Transform`` properties, set them together through `entity.components[Transform.self]` rather than setting ``doc://com.apple.RealityKit/documentation/RealityKit/HasTransform/position``, ``doc://com.apple.RealityKit/documentation/RealityKit/HasTransform/scale``, and ``doc://com.apple.RealityKit/documentation/RealityKit/HasTransform/orientation`` individually. Setting these convenience properties separately inside the closure generates independent animations that conflict, producing unexpected results.

## Respond to animation completion

Both [`animate(_:body:completion:)`](/documentation/RealityKit/Entity/animate(_:body:completion:)) and [`animate(body:completion:)`](/documentation/RealityKit/RealityViewContent/animate(body:completion:)) accept an optional `completion` closure. RealityKit calls this closure when the animation finishes. The completion closure also runs if a new animation begins on the same property before the current animation finishes.

Use the completion handler to chain animations or trigger follow-up logic. The following code example moves the entity to a new position, and the completion handler moves the entity back to the origin:

```swift
Entity.animate(.easeIn(duration: 0.8)) {
    entity.components[Transform.self]?.translation = SIMD3<Float>(0, 1.5, -2)
} completion: {
    Entity.animate(.easeOut(duration: 0.8)) {
        entity.components[Transform.self]?.translation = .zero
    }
}
```

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)