How do you detect multiple overlapping collisions along a raycast? I see that the raycast_source has a function called intersect_list()
. I would have expected that to have multiple collisions for overlapping objects, but it only appears to be detecting 1 object. You will see that in this example project where there is a large transparent sphere and a smaller sphere inside of it. Both have the same RayCastMesh
component.
And here is the code. I extended off of the mouse_picking.rs example:
use bevy::prelude::*;
use bevy_mod_raycast::{DefaultRaycastingPlugin, PluginState, RayCastMesh, RayCastMethod, RayCastSource, RaycastSystem, build_rays, update_debug_cursor, update_raycast};
// This example will show you how to use your mouse cursor as a ray casting source, cast into the
// scene, intersect a mesh, and mark the intersection with the built in debug cursor. If you are
// looking for a more fully-featured mouse picking plugin, try out bevy_mod_picking.
fn main() {
App::build()
.insert_resource(WindowDescriptor {
vsync: false, // We'll turn off vsync for this example, as it's a source of input lag.
..Default::default()
})
.add_plugins(DefaultPlugins)
.init_resource::<PluginState<Gizmoable>>()
.add_system_to_stage(
CoreStage::PreUpdate,
build_rays::<Gizmoable>.system().label(RaycastSystem::BuildRays),
)
.add_system_to_stage(
CoreStage::PreUpdate,
update_raycast::<Gizmoable>
.system()
.label(RaycastSystem::UpdateRaycast)
.after(RaycastSystem::BuildRays),
)
// Draw the debug rays
.add_system_to_stage(
CoreStage::PreUpdate,
update_debug_cursor::<Gizmoable>
.system()
.label(RaycastSystem::UpdateDebugCursor)
.after(RaycastSystem::UpdateRaycast),
)
// You will need to pay attention to what order you add systems! Putting them in the wrong
// order can result in multiple frames of latency. Ray casting should probably happen after
// the positions of your meshes have been updated in the UPDATE stage.
.add_system_to_stage(
CoreStage::PreUpdate,
update_raycast_with_cursor
.system()
.before(RaycastSystem::BuildRays),
)
.add_startup_system(setup.system())
.add_system(detect_selected.system())
.run();
}
// This is a unit struct we will use to mark our generic `RayCastMesh`s and `RayCastSource` as part
// of the same group, or "RayCastSet". For more complex use cases, you might use this to associate
// some meshes with one ray casting source, and other meshes with a different ray casting source."
struct Gizmoable;
struct TranslationGizmo;
struct RotationGizmo;
struct ScaleGizmo;
// Update our `RayCastSource` with the current cursor position every frame.
fn update_raycast_with_cursor(
mut cursor: EventReader<CursorMoved>,
mut query: Query<&mut RayCastSource<Gizmoable>>,
) {
for mut pick_source in &mut query.iter_mut() {
// Grab the most recent cursor event if it exists:
if let Some(cursor_latest) = cursor.iter().last() {
pick_source.cast_method = RayCastMethod::Screenspace(cursor_latest.position);
}
}
}
fn detect_selected(raycast_source: Query<&RayCastSource<Gizmoable>>) {
if let Ok(raycast_source) = raycast_source.single() {
let count = raycast_source.intersect_list().iter().count();
// I would have expected count to equal 2.
println!("{}", count)
}
}
// Set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
commands
.spawn_bundle(PerspectiveCameraBundle::default())
.insert(RayCastSource::<Gizmoable>::new()); // Designate the camera as our source
commands
.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere::default())),
material: materials.add(Color::rgb(1.0, 1.0, 1.0).into()),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, -5.0)),
..Default::default()
})
.insert(RayCastMesh::<Gizmoable>::default()); // Make this mesh ray cast-able
commands
.spawn_bundle(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {
radius : 2.0,
subdivisions: 5
})),
material: materials.add(Color::rgba(1.0, 1.0, 1.0, 0.5).into()),
transform: Transform::from_translation(Vec3::new(1.0, 0.0, -5.0)),
..Default::default()
})
.insert(RayCastMesh::<Gizmoable>::default()); // Make this mesh ray cast-able
commands.spawn_bundle(PointLightBundle {
transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)),
..Default::default()
});
}