Reputation: 667
I'm working on a VisionOS app but I'm a bit stuck on placing entities within an immersive space.
What I want:
ImmersiveSpace
DragGesture()
The issue I'm having is gesture and position don't seem to play well with each other. I can position the sphere correctly, but when it's dragged it jumps up in the view. It's as if the original position is added again making it jump.
Here's my code so far:
// ImmersiveView.swift
import SwiftUI
import RealityKit
import RealityKitContent
struct ImmersiveView: View {
@State private var entity = Entity()
var body: some View {
RealityView {
content in
do {
entity = try await Entity(named: "Sphere", in: realityKitContentBundle)
let anchor = AnchorEntity(.head)
anchor.anchoring.trackingMode = .once
entity.setParent(anchor)
content.add(anchor)
entity.position = SIMD3<Float>(0, 0, -1)
entity.name = "Head Anchor"
} catch {
print("Error loading Sphere model: \(error.localizedDescription)")
}
}
.gesture(
DragGesture()
.targetedToEntity(entity)
.onChanged { value in
(entity).position = value.convert(
value.location3D,
from: .local,
to: (entity).parent!
)
}
)
}
}
Upvotes: 1
Views: 1058
Reputation: 58113
You need an intermediate property to store model's translation value in 3D space.
import SwiftUI
import RealityKit
import RealityKitContent
struct ContentView: View {
@State var sphere = Entity()
@State var translation: Vector3D = .zero
let anchor = AnchorEntity(.head, trackingMode: .once)
var gesture: some Gesture {
DragGesture()
.targetedToEntity(sphere)
.onChanged {
$0.entity.position = $0.convert(
$0.translation3D + translation,
from: .local,
to: sphere)
}
.onEnded {
translation += $0.translation3D
}
}
var body: some View {
RealityView { content in
// rkcb is realityKitContentBundle
sphere = try! await Entity(named: "Scene", in: rkcb)
sphere.scale *= 5
sphere.position = [0, 1,-4]
anchor.addChild(sphere)
content.add(anchor)
}
.gesture(gesture)
}
}
Upvotes: 1