GestureComponent does not support DragGesture

The following code using the new GestureComponent demonstrates inconsistency. The tap gesture prints output, but the drag gesture does not.

I already checked this post, which points to this seemingly outdated sample code

I assume that example is deprecated in favour of the now built in version of GestureComponent.

Nonetheless, there are no compiler warnings or errors, it just fails silently.

TapGesture, LongPressGesture, MagnifyGesture, RotateGesture all work, so this feels like an oversight.

RealityView { content in
            let testEntity = ModelEntity(mesh: .generateBox(size: .init(x: 1, y: 1, z: 1)))
            testEntity.position = SIMD3<Float>(0,0,-1)
            testEntity.components.set(InputTargetComponent())
            testEntity.components.set(CollisionComponent(
                shapes: [.generateBox(size: .init(x: 1, y: 1, z: 1))]
            ))
            
            let testGesture = TapGesture()
                .onEnded { value in
                    print("Tapped")
                }
            testEntity.components.set(GestureComponent(testGesture))
            
            let dragGesture = DragGesture()
                .onEnded { value in
                    print("Dragged")
                }
            testEntity.components.set(GestureComponent(dragGesture))
            
            content.add(testEntity)
        }
Answered by Vision Pro Engineer in 848954022

Hi @eurobob

Can you try setting the minimumDistance of your DragGesture to a small value, such as 0.001:

let dragGesture = DragGesture(minimumDistance: 0.001)

It looks like DragGesture is defaulting to a minimumDistance of 10 meters in this use case, which is likely too large for the gesture to trigger naturally. A smaller value should give you the expected behavior.

Let me know if you're still running into issues after trying that!

Accepted Answer

Hi @eurobob

Can you try setting the minimumDistance of your DragGesture to a small value, such as 0.001:

let dragGesture = DragGesture(minimumDistance: 0.001)

It looks like DragGesture is defaulting to a minimumDistance of 10 meters in this use case, which is likely too large for the gesture to trigger naturally. A smaller value should give you the expected behavior.

Let me know if you're still running into issues after trying that!

Just jumping in to confirm the issue that @eurobob reported. @Vision Pro Engineer suggested adding a minimalDistance, which works for me.

There is something else that could be causing issues. As we know, an Entity can only have one instance of a component type assigned at a time. Add a GestureComponent with Gesture B will overwrite a GestureComponent with Gesture A. I don't see a clear way to add more than one Gesture to a GestureComponent. The docs for this one are essentially, so no help there. Is it possible to use this component with more than one gesture?

struct Lab: View {
    var body: some View {
        RealityView { content in

            // Load an entity and set it up for input
            let subject = ModelEntity(
                mesh: .generateBox(size: 0.2, cornerRadius: 0.01),
                materials: [SimpleMaterial(color: .stepGreen, isMetallic: false)]
            )
            subject.name = "Subject"
            subject.components.set(InputTargetComponent())
            subject.components.set(HoverEffectComponent())
            subject.components
                .set(CollisionComponent(shapes: [.generateBox(width: 0.2, height: 0.2, depth: 0.2)], isStatic: false))

            // This works as long as this is the only gesture we use
            let gesture = DragGesture(minimumDistance: 0.001)
                .onChanged({ [weak subject] _ in
                    print("Drag Gesture onChanged for \(subject!.name)")
                })
                .onEnded({ [weak subject] _ in
                    print("Drag Gesture onEnd for \(subject!.name)")
                })
            let gestureComponent = GestureComponent(gesture)
            subject.components.set(gestureComponent)

            let tapGesture = TapGesture()
                .onEnded({ [weak subject] _ in
                    print("Tap Gesture Works for \(String(describing: subject))")
                })
            let gestureComponent2 = GestureComponent(tapGesture)
            subject.components.set(gestureComponent2)

            content.add(subject)

        }
    }
}

If I comment out the second gesture component, then the drag gesture works correctly

Hey @radicalappdev,

You can use simultaneously(with:) to provide multiple gestures to a single gesture component:

sphere.components.set(GestureComponent(
    DragGesture(minimumDistance: 0.001)
        .onChanged { _ in
            print("Drag Gesture onChanged")
        }
        .onEnded { _ in
            print("Drag Gesture onEnd")
        }
        .simultaneously(with: SpatialTapGesture().onEnded { _ in
            print("Tap onEnd")
        })
))

Hope this helps,
Michael

GestureComponent does not support DragGesture
 
 
Q