#bevy_mod_raycast
85 messages Β· Page 1 of 1 (latest)
Copying this question from @dusky copper
Hello, I'm using bevy_mod_raycast and it works very good. The problem I have however, is that I cannot get the component of an entity that is hit. I can get the transform with if let Ok(transform_entity) = transform_query.get(intersection.0) {, transform_query being mut transform_query: Query<&Transform>, and intersection.0 being of type Entity . I tried the exact same with a Component of mine. Anybody knows what I am doing wrong? I also tried to add the RaycastMesh::<()>::default(), to my spawn command. Or do I already need the bevy_mod_picking for this use case?
If the raycasting system is returning an Entity, that will correspond with the Entity that has the Mesh that was intersected.
My best guess is that your component has not been added to the entity with the Mesh, but rather as a child or on some other entity.
The RaycastMesh component is only required if you have turned on that setting.
0.12 support soon, yes? π
Whenever I get the time, yes.
sure! it's just i saw the PR get approved but it wasn't merged so i was wondering
To be quite frank I dont know the difference 100% between the two methods but I tried both anyway:
mesh: ...,
material: ...,
transform: ...,
..Default::default()
},
RaycastMesh::<()>::default(),
)).insert(Zombie {...},);
commands.spawn((
PbrBundle {
mesh: ...,
material: ...,
transform: ...,
..Default::default()
},
Zombie {...},
RaycastMesh::<()>::default(),
));```
You can use code formatting by putting everything inside a code block
```rs
```
Both are valid, the second one is maybe more idiomatic.
But should be fine either way.
Am I maybe doing something wrong here: ```
pub fn strategy_camera_mouse_button_system(
time: Res<Time>,
mut mouse_button_event_reader: EventReader<MouseButtonInput>,
mut zombie_query: Query<&Zombie>,
mut transform_query: Query<&Transform>,
cursor_ray: Res<CursorRay>,
mut raycast: Raycast,
mut gizmos: Gizmos,
) {
for event in mouse_button_event_reader.iter() {
if event.button == MouseButton::Left {
if let Some(cursor_ray) = **cursor_ray {
// raycast.debug_cast_ray(cursor_ray, &default(), &mut gizmos);
let intersections = raycast.cast_ray(cursor_ray, &default());
println!("intersections: {}", intersections.len());
for intersection in intersections {
println!("intersection position: {}", intersection.1.position());
let entity = intersection.0;
if let Ok(zombie_entity) = zombie_query.get(intersection.0) {
println!("zombie intersection position: {}", intersection.1.position());
}
if let Ok(transform_entity) = transform_query.get(intersection.0) {
println!("transform intersection position: {}", intersection.1.position());
}
println!("-------");
}
}
}
}
} ```
What happens?
The transform works fine, like I said earlier and in debug_cast all of my objects are clearly hit
This always gets called when I click on my meshes println!("intersection position: {}", intersection.1.position()); and intersections.len() is always 1
Maybe try spawning a single zombie, and printing it's entity id using let id = spawn(..).id();. Then print out the entity that is being hit with the raycast.
good idea, I will try it
I print the Id of my component on creation, it is 406. I print the entity id on click it is also 406. Then it seems like it is not related to your plugin
I want to do a drag selection where an area of entities is selected. Like for example on a desktop or in a strategy game. I guess I could cast a lot of rays in an area and put all the hit entities in a Set. Is there maybe an built in way to do this or is maybe there is a better approach?
You'd be better off using a physics engine and colliders.
You want a spatial query - "which entities intersect with the selection box?"
If you are working on a 2d plane, you could simplify this though, and just look at the entities' translation and check if it is inside the bounds.
Okay, thanks for the input π
hello, the raycasting works great, but when I modify the mesh vertices to new positions, the raycast seems to not hit the new bounds of the mesh, only hitting the old parts. how should I fix this?
for context I'm using the CursorRay and the immediate mode Raycast
atm i don't know how to update Aabb manually but there must be a way
I am messing with the filter attribute of RaycastSettings and I can't for the life of me get the correct result. Here is some context:
I am trying to build a system that places a model (random .glb file) against a plane. The problem is that I want to place the model to where my cursor hits the plane, and the raycast that I use to find the position only detects that of the model that I am placing. Here is some code:
let should_be_picked: &dyn Fn(Entity) -> bool = &(|filter_entity: Entity| -> bool {
println!("{}, {}", entity.index(), filter_entity.index()); // Numbers never equal eachother
return entity.index() != filter_entity.index();
});
if let Some(cursor_ray) = **cursor_ray {
let intersection_array = &raycast.cast_ray(
cursor_ray,
&RaycastSettings {
filter: should_be_picked,
..default()
},
);
let intersection_data = &intersection_array[0].1;
transform.translation = intersection_data.position();
}
Here, I get the entity from a query of the model. For whatever reason, the indexes of the filter_entity and the model entity are never the same, so I can't properly filter them. Thanks for reading!
why are you comparing the entity.index, instead of just comparing the entities directly?
Because I didn't know you could compare the entities directly. Also I thought that an entity's index was unique, so it shouldn't matter
It is probably okay, but indices aren't necessarily unique, because you are ignoring the generation. https://docs.rs/bevy/latest/bevy/ecs/entity/struct.Entity.html#method.index
I also don't understand why you are using !=
I assume you want the filter to look like
&RaycastSettings {
filter: |entity| entity == plane_entity,
..default()
},
If the entity that I am moving equals that of the current entity I am filtering, then I want it to skip that entity
That way I could use it for more than just a plane
That means it will intersect everything else, and I thought you just want it to check against the plane?
Yeah my bad forgot to say that
Every mesh inside your glb will have its own entity fwiw
Ah damn well thatβs probably why
The scene is the parent, and all meshes are child entities
(Sorry to dig up this old thread, but)... is it possible to get the SceneBundle when the ray hits one of the child entities? I'm loading a .gltf model of a car (which is made up of multiple meshes) but I'd like to get the data from my SceneBundle when the ray hits one of the child meshes.
No, you will need to traverse the hierarchy yourself.
It's pretty easy to do, but not within the scope of the plugin.
You just need to look at the Parent of the entity recursively, until you find the scene at the root.
Ah, of course. Thanks! (And thank you for the awesome plugin... having a blast with it!)
Not sure if this is a horrible way to do it, but anyone was looking for a quick-n-dirty way to get the root entity (like for a gltf SceneBundle as I described above), this appears to work:
fn raycast(
mut cmds: Commands,
mut raycast: Raycast,
parent: Query<&Parent>
) {
... // set up your Ray3d and RaycastSettings
let hits = raycast.cast_ray(ray, &settings);
if let Some((e, hit)) = hits.first() {
let root = match parent.iter_ancestors(*e).last() {
Some(root) => root,
None => *e
};
cmds.entity(root).insert(SomeHitMarker);
}
}
Then you can get the entity (and any other of its components) by querying Added<SomeHitMarker>.
Oh, right, I forgot about iter_ancestors. Back in my day we had to do it manually. Uphill both ways, in the snow.
Is ray casting a good way to check if an entity is visible to a camera? Or is there a better solution to that problem?
(I want to query for the objects a camera can "see", taking into account occlusions and reflections)
Use the visibility component
It is automatically updated for you by bevy
and it tells you if the entity is visible to any camera, or if it is visible to a camera and in the hierarchy, which is probably what you want
Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering.
Yeah, it was renamed
noob here!
can i borrow the Raycast object into a par_iter_mut closure inside my System?
here's a code snippet showing what i'm trying to do:
// Frustum culling and occlusion detection.
pub fn mark_visible_entities(
mut view_query: Query<(...)>,
mut aabb_query: Query<(...)>,
mut raycast: Raycast,
) {
for (...) in &mut view_query {
aabb_query.par_iter_mut().for_each(|query_item| {
...
let hits = raycast.cast_ray(ray, &raycast_settings);
...
The error I get:
33 | visible_aabb_query.par_iter_mut().for_each(|query_item| {
= note: `Clone` is implemented for `&bevy_mod_raycast::immediate::Raycast<'_, '_>`, but not for `&mut bevy_mod_raycast::immediate::Raycast<'_, '_>`
It looks like you are trying to clone a mutable reference
That is not allowed.
From what I can tell, you are trying to running raycasts in parallel, this is not possible, because reaycasting requires a mutable reference to data. You can not have multiple mutable references to the same data.
Raycasts are already run in parallel, you would be better off running each raycast serially.
Ah, i wasn't aware i couldn't run them in parallel. What's the mutable reference needed for? Index updates?
any convenient way to visualize/debug raycasts?
i have xpbd debug wireframes enabled but i guess raycasts aren't going to get rendered that wayunless i add placeholder entities for all the raycasts i'm doing
nm, this worked: gizmos.ray(origin, direction, Color::BLUE);
There is a builtin for debugging raycasts
just replace cast_ray with debug_cast_ray
It will show a debug ray and point at the ray source and on any hits, including normals
please ignore me - i was confused by the debug normals
hi just switched to new version and trying to update my code - what's the new version of intersect_primitive?
(the method that was on RayCastSource)
Is it possible to mark some meshes to be ignored without using filters ? The same way NoBackfaceCulling work
Are you using the immediate or deferred raycasting?
I am using immediate
Hello, could a maintainer check this ? https://github.com/aevyrie/bevy_mod_raycast/issues/123
Is this addon still being maintained? There seems to be MRs to get it running on Bevy 0.15 have been open for a while https://github.com/aevyrie/bevy_mod_raycast/pull/127 https://github.com/aevyrie/bevy_mod_raycast/pull/128
Not really. The mesh raycasting has been upstreamed, but I haven't gotten around to tidying things up.
I see, the only dependency I have for this crate is bevy_transform_gizmo.
$ cargo tree -i bevy_mod_raycast --depth 1
bevy_mod_raycast v0.18.0
βββ bevy_picking_raycast v0.20.0
βββ bevy_transform_gizmo v0.12.1
$ cargo tree -p bevy_transform_gizmo --depth 1
bevy_transform_gizmo v0.12.1
βββ bevy v0.14.0
βββ bevy_mod_picking v0.20.1
βββ bevy_mod_raycast v0.18.0
Has this crate been replaced by another for Bevy 0.15 as well?