bevy-picking
ResearchReference for Bevy's picking system — pointer events, backends, hover/click/drag observers, sprite picking, UI picking, and mesh picking.
How to use this skill
Bring this guide into your coding agent with a prompt tailored to the tool you use.
- Open your project in Codex.
- Copy and paste the prompt below.
- Review files and risks before approving any action.
Inspect the Agent Skill at https://github.com/nolantait/bevy-starter/blob/HEAD/.agents/skills/bevy-picking/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/bevy-picking, but wait for my approval before writing files or running scripts.
Copying this prompt does not install or run the skill. Review third-party files before use.
Core concept
Pointer is an abstract representation of user input at a screen location. Backends read PointerLocation components and produce PointerHits events. The picking pipeline handles the rest.
Default picking plugins
DefaultPickingPlugins (included with DefaultPlugins when bevy_picking feature enabled) contains:
InteractionPlugin— generates pointer events, handles bubblingPickingPlugin— manages picking state, produces higher-level eventsPointerInputPlugin— mouse and touch events
Pointer event types
Hovering
Pointer<Over>— pointer entered entity boundsPointer<Move>— pointer moving over entityPointer<Out>— pointer left entity bounds
Clicking
Pointer<Press>/Pointer<Release>— button pressed/releasedPointer<Click>— press + release on same entity
Dragging
Pointer<DragStart>/Pointer<Drag>/Pointer<DragEnd>Pointer<DragEnter>/Pointer<DragOver>/Pointer<DragDrop>/Pointer<DragLeave>
Picking sprites
Enable with Pickable component:
commands.spawn((
Sprite::from_color(GREEN, Vec2::new(100., 100.)),
Pickable::default(),
)).observe(|hover: On<Pointer<Over>>, mut sprites: Query<&mut Sprite>| {
sprites.get_mut(hover.entity).unwrap().color = YELLOW.into();
});
Picking UI
UI nodes are pickable by default. Attach observers to specific elements:
commands.spawn(button()).observe(|click: On<Pointer<Click>>| {
info!("Button clicked!");
});
Picking meshes (3D)
Add MeshPickingPlugin. Use observers on mesh entities:
commands.spawn((
Mesh3d(meshes.add(Cuboid::from_length(5.))),
MeshMaterial3d(materials.add(Color::from(SILVER))),
)).observe(|drag: On<Pointer<Drag>>, mut transforms: Query<&mut Transform>| {
let mut t = transforms.get_mut(drag.entity).unwrap();
t.rotate_y(drag.delta.x * 0.02);
t.rotate_x(drag.delta.y * 0.02);
});
Ignoring entities
Pickable::IGNORE // disables picking on this entity
Set MeshPickingSettings::require_markers to true for opt-in mesh picking.
Picking pipeline order
- Input → update pointers →
PointerInputevents - Update
PointerLocationcomponents - Backends read locations → produce
PointerHits - Build
HoverMap(topmost entity wins) - Generate higher-level
Pointer<E>events
Within a frame: Out/DragLeave first, then DragEnter/Over, then movement/press/drag events in any order.