Lab 034 – Teleport to waypoints

We can teleport to fixed locations without changing the users orientation in the scene.

In this lab we’ll use TapGesture to teleport directly to the position of the tapped entity. We don’t need to use SpatialTapGesture since we don’t need a location on the entity, just the location of the entity. Remember, we can’t move the player/user entity in RealityKit, but we can move the world around them instead. We’ll also keep the user facing the same direction in the scene.

let vectorToTap = value.entity.position

We can normalize the vector to get a direction.

let direction = normalize(vectorToTap)

We can get the distance to the tapped position by getting the length relative to the global space.

let distance = length(vectorToTap)

Then we can multiply these to get a new position. Remember, we can’t use this position to move the player. Instead, we’ll invert this so we can use it to move the world. In this case, that means moving the root entity of our scene.

let newPosition = -direction * distance

In the next teleport lab, we’ll look at using the orientation of the tapped entity to adjust the users point of view in the scene.

Video Demo

Full Lab Code

struct Lab034: View {

    @State var sceneContent: Entity?

    var body: some View {
        RealityView { content in
            if let scene = try? await Entity(named: "TeleportLabs", in: realityKitContentBundle) {
                content.add(scene)

                // Get the scene content and stash it in state
                if let sceneContent = scene.findEntity(named: "Root") {
                    self.sceneContent = sceneContent
                }

            }
        }
        .gesture(teleportTapWaypoint)
    }

    var teleportTapWaypoint: some Gesture {
        TapGesture()
            .targetedToAnyEntity()
            .onEnded { value in

                guard let sceneContent = self.sceneContent else { return }

                // Calculate the vector from the origin to the tapped position
                let vectorToTap = value.entity.position

                // Normalize the vector to get a direction from the origin to the tapped position
                let direction = normalize(vectorToTap)

                // Calculate the distance (or magnitude) between the origin and the tapped position
                let distance = length(vectorToTap)

                // Calculate the new position by inverting the direction multiplied by the distance
                let newPosition = -direction * distance

                // Update sceneOffset's X and Z components, leave Y as it is
                sceneContent.position.x = newPosition.x
                sceneContent.position.z = newPosition.z
            }
    }
}

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

Questions or feedback?

2 Comments

  1. Hello, does this work even if users moves a bit. Meaning I want to have user be able to move freely but when in close space letting him use teleportation spheres so that he can view bigger scenes in enclosed spaces. Since now with all the things I tried im always getting move to sphere + offset of the movement of user.

    1. These teleport labs apply the offset to the origin point when each calculation runs. In visionOS that is the a point on the floor directly below the user when they first enter the immersive space. This point is updated if they recenter their view using the Digital Crown. To accomplish your goal you would need to add a vector offset for the users current distance to the origin.