Support generating or redirecting rays for picking
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
## What need does this fill?
- Being able to pick an entity through a portal (that's my use case for `bevy_basic_portals`)
- Idk maybe leveraging the picking system in a testing environment or as a intradiegetic game mechanic that doesn't involve the cameras/screen position directly? Like an ennemy that would be able to pick stuff like the player, but would do so with the picking logic?
**More details** about why this is complicated to do currently (tl;dr: `RayMap` cannot be mutated outside of Bevy's logic and the backends can't be called several times in a practical way so you can't rely on their result to call them again with new rays):
https://discord.com/channels/691052431525675048/1314258126832271381/1314258126832271381
**Related issue**: https://github.com/bevyengine/bevy/issues/16046
## What solution would you like?
I see several options:
- Make "ray-based" backends have a hook to allow to subscribe handles to generate new rays (`RayId` + `Ray3d`) in certain conditions on hit, those new rays are then reprocessed to send new `PointerHits` and generate other rays, etc until there's no ray left, this requires like Avian and Rapier to use this hook, and a logic to avoid infinite loops (I think this could be one of the more elegant solutions?). This solution allows to pass in the incoming ray to calculate the generated one, otherwise this information is lost or needs to be recreated with `PointerHits`/`HitData`.
- Have a component in Bevy on some entities (like a portal) to allow to redirect picking rays with a closure or something, similar as the hook solution but the hook would be on the entities instead of subscribed in a list.
- Make `RayMap` mutable (no private fields or setters) and being able to not be cleared at the beginning of the frame, that would allow to generate rays that are picked up next frame. This is not an elegant solution at all as there would be a delay in how the inputs are handled, and could generate a delayed infinite loop.
- Make "ray-based" backends register their system in a subset of `PickSet::Backend`, like `PickSet::RayBasedBackend`, and make `RayMap` mutable, so that those systems could be recalled once after with a different RayMap, without having to recall them one by one. This doesn't allow recursion.
- Rewrite `update_hits` so that it's a system calling a function using a `RayMap` not necessarily the ressource one, so that this function can then be called to handle the hit detection and do other stuff with it, and convinced Rapier and Avian to do the same (still backend-dependent)
## What alternative(s) have you considered?
For my case, copying `update_hits` into `bevy_basic_portals` but modify its logic so that it operates on the `RayMap` ressource but also on potential portal-deviated rays.
This solution is not very satisfying as it not only duplicates code but also relies on Bevy's Mesh picking algorithm and doesn't leverage potential colliders / other backends.
Contributor guide
Assessment
This issue has not been assessed yet.