From build-visionos-apps
Wire visionOS input — spatial taps, drags, rotate, magnify gestures on RealityKit entities, plus hover effects and the eye/hand privacy model. Use when making 3D content interactive or adding gestures to entities.
How this skill is triggered — by the user, by Claude, or both
Slash command
/build-visionos-apps:spatial-gestures-interactionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
On visionOS the user looks at a target (eyes) and pinches/taps (hands); the system
On visionOS the user looks at a target (eyes) and pinches/taps (hands); the system resolves this privately and delivers it to your content. Use this skill to make RealityKit entities interactive with SwiftUI gestures, add hover feedback, and respect the eye/hand privacy model. This makes a model viewer manipulable (rotate, scale, move, tap-to-select).
A gesture only hits an entity if that entity has both:
InputTargetComponent() — marks it as interactive, andCollisionComponent, e.g. via generateCollisionShapes).entity.components.set(InputTargetComponent())
entity.generateCollisionShapes(recursive: true)
Missing either → the gesture silently does nothing. This is the #1 cause of "my gesture doesn't fire".
Attach SwiftUI gestures to a RealityView and target them to entities:
RealityView { content in /* add entities w/ input target + collision */ }
// Tap to select
.gesture(
SpatialTapGesture()
.targetedToAnyEntity()
.onEnded { value in
let entity = value.entity
// value.location3D is the world hit point
}
)
// Drag to move
.gesture(
DragGesture()
.targetedToAnyEntity()
.onChanged { value in
value.entity.position = value.convert(value.location3D,
from: .local, to: value.entity.parent!)
}
)
// Rotate (one-/two-handed) and Magnify (scale)
.gesture(rotateGesture)
.gesture(magnifyGesture)
var rotateGesture: some Gesture {
RotateGesture3D() // 3D rotation
.targetedToAnyEntity()
.onChanged { value in
value.entity.orientation = simd_quatf(value.rotation)
}
}
var magnifyGesture: some Gesture {
MagnifyGesture()
.targetedToAnyEntity()
.onChanged { value in
let s = Float(value.magnification)
value.entity.scale = SIMD3(repeating: s)
}
}
Use .targetedToEntity(_:) to bind to one specific entity, or
.targetedToAnyEntity() for any interactive entity hit.
For smooth drag/scale, capture the entity transform at gesture start so changes
are relative, not absolute (store in @State or a gesture-scoped value), then
apply deltas. Reset on .onEnded.
Give eye/pointer feedback without code knowing where the user looks:
entity.components.set(HoverEffectComponent()) // RealityKit entity
// or in SwiftUI views:
someView.hoverEffect()
HoverEffectComponent supports styles (highlight/spotlight) and can drive a
ShaderGraph parameter for custom hover looks.
arkit-spatial).InputTargetComponent + collision shapes..targetedTo...Entity and attached to the RealityView.HoverEffectComponent/.hoverEffect).references/spatial-gestures.md: tap/drag/rotate/magnify recipes, coordinate conversion.references/hover-and-input.md: hover effects, input components, privacy model, ergonomics.onChanged (fires every frame).State which entities are interactive, the gestures wired, how transforms are applied (delta vs absolute), and the hover/feedback approach.
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub likw99/agent-plugins --plugin build-visionos-apps