Working with Behaviors

We can use Behaviors in Reality Composer Pro run Timelines that contain one or more actions.

Overview

Timelines in RealityKit are a feature of Reality Composer Pro. Understanding timelines means learning three concepts

  1. Behaviors trigger a timeline.
  2. Timelines are containers for one or more Entity Actions. See Working with Timelines.
  3. Entity Actions can update entity components. See Working with Entity Actions.

One of the components we can add in Reality Composer Pro (but not in code) is Behaviors. This simple component lets us define a trigger and a timeline. When the behavior is triggered, it will run the selected timeline. There are four behaviors as of November 2026.

  • On Tap
  • On Collision
  • On Added to Scene
  • On Notification

We’ll dive deeper into Timelines in other examples. Today, let’s learn the Behaviors.

On Tap Behavior

This one is the simplest to start with. When we tap an entity, we will perform an action. Easy, right? But we need to keep in mind that a TapGesuture won’t actually trigger this behavior unless we ask it to. We need to call this Entity instance method: applyTapForBehaviors(). This returns a boolean that is true when Reality Kit finds a Behavior with a selected timeline.

guard let car = scene.findEntity(named: "ToyCar") else { return }
let tapGesture = TapGesture()
    .targetedToEntity(car)
    .onEnded { value in
        let didTap = value.entity.applyTapForBehaviors()
        _ = value.entity.applyTapForBehaviors() // if you don't care about the result.
        print("did tap car: \(didTap)")
    }
car.components.set(GestureComponent(tapGesture))

Read more: On Tap Behavior and the need for better documentation

On Added to Scene

This is the one we use most often. It is useful for starting timelines that need to run in a loop, such as ambient sounds and animations. For this example, we created a timeline called SpinRocket. Then a second timeline called LoopRocket that calls the first one in a loop. When the scene is loaded, the Rocket will spin around the Y axis until we close the scene.

Call a looping timeline on scene start.

On Notification

This Behavior is useful when we need to trigger a timeline from somewhere else in our app. For example, when data has loaded, state has changes, or on user input. We’ll use a SwiftUI button to send the notification.

Button(action: {
    notifyTimeline("JumpThePlane")
}, label: {
    Text("Jump the Plane")
})

Learn more about Working with Notifications, including two-way communication.

When the entity receives the notification for “JumpThePlane” it will run a timeline to add an upward force.

JumpPlane timeline

On Collision

We can call a Timeline when the entity collides with another entity. In this case, we’ll stick with the plane. When the plane lands back on the base, we’ll trigger another timeline.

Video Demo

Check out all four Behaviors in this short video.

  • The rocket starts spinning on scene launch
  • The car flips when we tap it
  • Tapping the button sends a notification to jump the plane
  • The plane spins when landing on the base

You can add as many behaviors as you need. For example, you could create a character entity that runs different timelines based on the other entities it collisions with. Or an entity that can receive multiple notifications.

Example Code

Make sure to check out the SimpleBehaviors scene in the Reality Composer Pro bundle in the repo.

struct Example120: View {

    @Environment(\.realityKitScene) var scene

    var body: some View {
        RealityView { content in

            guard let scene = try? await Entity(named: "SimpleBehaviors", in: realityKitContentBundle) else { return }
            scene.position.y = -0.4
            content.add(scene)

            guard let car = scene.findEntity(named: "ToyCar") else { return }
            let tapGesture = TapGesture()
                .targetedToEntity(car)
                .onEnded { value in

                    let didTap = value.entity.applyTapForBehaviors()
                    print("did tap car: \(didTap)")

                }
            car.components.set(GestureComponent(tapGesture))

        }
        .toolbar {
            ToolbarItem(placement: .bottomOrnament, content: {
                Button(action: {
                    notifyTimeline("JumpThePlane")
                }, label: {
                    Text("Jump the Plane")
                })
            })
        }

    }
    func notifyTimeline(_ identifier: String) {
        if let scene = scene {
            NotificationCenter.default.post(
                name: NSNotification.Name("RealityKit.NotificationTrigger"),
                object: nil,
                userInfo: [
                    "RealityKit.NotificationTrigger.Scene": scene,
                    "RealityKit.NotificationTrigger.Identifier": identifier
                ]
            )
        }
    }
}

Support our work so we can continue to bring you new examples and articles.

Questions or feedback?