Canvatorium Visio Lab 5017
Moving the World instead of the Player.
Using some vector math to move a single parent entity when its children are tapped.
RealityView lacks access to the player or camera. I wanted a simple movement/locomotion feature for Project Graveyard and I’m not ready to give up on RealityView just yet.
I suck at vector math.
struct Lab5017: View {
@State var selected: String = "Tap Something"
@State var sceneContent: Entity?
@State var sceneContentPosition: SIMD3<Float> = [0,0,0]
var tap: some Gesture {
SpatialTapGesture()
.targetedToAnyEntity()
.onEnded { value in
selected = value.entity.name
// 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
sceneContentPosition.x = newPosition.x
sceneContentPosition.z = newPosition.z
}
}
var body: some View {
RealityView { content, attachments in
if let model = try? await Entity(named: "5017Move", in: realityKitContentBundle) {
content.add(model)
// Get the scene content and stash it in state
if let floorParent = model.findEntity(named: "SceneContent") {
sceneContent = floorParent
sceneContentPosition = floorParent.position
}
}
//Position the attachment somewhere we can see it
if let attachmentEntity = attachments.entity(for: "SelectedLabel") {
attachmentEntity.position = [0.8, 1.5, -2]
attachmentEntity.scale = [5,5,5]
content.add(attachmentEntity)
}
} update: { content, attachments in
// Update the position of scene content anytime we get a new position
sceneContent?.position = sceneContentPosition
} attachments: {
Attachment(id: "SelectedLabel") {
Text(selected)
.font(.largeTitle)
.padding(18)
.background(.black)
.cornerRadius(12)
}
}
.gesture(tap) // The floor child entities can receive input, so this gesture will fire when we tap them
}
}