I've been having a very hard time with this and wonder if there's any way bevy_rapier might make this easier. I'm trying to integrate physics into my pathfinding, which can take more than a single frame. Previously, my AStar calls generated paths that routed entities through areas in which they couldn't physically fit. I'm trying to add shapes to this algorithm such that valid successors to a given tile are only those in which the shape of the source entity can fit. Here's an example of what I have right now:
fn find_path_for_shape(
pool: &AsyncComputeTaskPool,
initiator: Entity,
start: &dyn PointLike,
destination: &dyn PointLike,
map: &Map,
query_pipeline: &QueryPipeline,
collider_query: &QueryPipelineColliderComponentsQuery,
shape: &dyn Shape,
channel: &Sender<Option<Path>>,
) {
let collider_set = QueryPipelineColliderComponentsSet(&collider_query);
let shapes = Shapes(
collider_query
.iter()
.map(|(a, b, c, d)| (a, b.clone(), c.clone(), d.clone()))
.collect::<Vec<(Entity, ColliderPosition, ColliderShape, ColliderFlags)>>(),
);
let start = start.i32();
let destination = destination.i32();
let map_clone = map.clone();
let shape_clone = shape.clone();
let channel_clone = channel.clone();
pool.spawn(async {
let path = astar(
&start,
|p| {
let mut successors: Vec<((i32, i32), u32)> = vec![];
for tile in map_clone.get_available_exits(p.0 as usize, p.1 as usize) {
let mut should_push = true;
let shape_pos = Isometry::new(vector![tile.0 as f32, tile.1 as f32], 0.);
query_pipeline.intersections_with_shape(
&shapes,
&shape_pos,
&*shape_clone,
InteractionGroups::all(),
Some(&|v| v.entity() != initiator),
|handle| {
should_push = false;
false
},
);
if should_push {
successors.push(((tile.0 as i32, tile.1 as i32), (tile.2 * 100.) as u32));
}
}
successors
},
|p| (p.distance_squared(&destination) * 100.) as u32,
|p| *p == destination.into(),
);
channel_clone
.send(if let Some(path) = path {
Some(Path(path.0))
} else {
None
})
.expect("Channel should exist");
})
.detach();
}
It was suggested that I make a wrapper type that creates a static snapshots of colliders to pass into the pool. I'm fine with this, as I can probably correct for changes in the system that actually negotiates calculated paths for cases where a path gets blocked. Here is a partial attempt at that:
error[E0621]: explicit lifetime required in the type of shape
--> src\pathfinding.rs:129:10
|
114 | shape: &dyn Shape,
| ---------- help: add explicit lifetime 'static to the type of shape: &'static (dyn bevy_rapier2d::prelude::Shape + 'static)
...
129 | pool.spawn(async {
| ^^^^^ lifetime 'static required
error[E0621]: explicit lifetime required in the type of query_pipeline
--> src\pathfinding.rs:129:10
|
112 | query_pipeline: &QueryPipeline,
| -------------- help: add explicit lifetime 'static to the type of query_pipeline: &'static bevy_rapier2d::prelude::QueryPipeline
...
129 | pool.spawn(async {
| ^^^^^ lifetime 'static required
This is probably a more advanced use case, and I'm not sure what the plugin might do to make this easier. Maybe even an example of snapshotting collision data and accessing it in a pool would be useful? There are some obvious mistakes in my Shapes code--Rust Analyzer's automatic import added a few broken paths, for instance--but I feel like I'm adding mud to an existing mess rather than working toward a solution. Alternately, I'm not sure if there's a better solution to my pathfinding issue than taking physical shapes into account, but I had enough special cases for handling bad data that I thought it might help to prevent that bad data from being generated in the first place.
I've been having a very hard time with this and wonder if there's any way bevy_rapier might make this easier. I'm trying to integrate physics into my pathfinding, which can take more than a single frame. Previously, my AStar calls generated paths that routed entities through areas in which they couldn't physically fit. I'm trying to add shapes to this algorithm such that valid successors to a given tile are only those in which the shape of the source entity can fit. Here's an example of what I have right now:
It was suggested that I make a wrapper type that creates a static snapshots of colliders to pass into the pool. I'm fine with this, as I can probably correct for changes in the system that actually negotiates calculated paths for cases where a path gets blocked. Here is a partial attempt at that:
Obviously that's incomplete, but here are some of the errors I'm getting:
error[E0284]: type annotations needed: cannot satisfy
<_ as SliceIndex<[(bevy::prelude::Entity, bevy_rapier2d::prelude::ColliderPosition, bevy_rapier2d::prelude::SharedShape, bevy_rapier2d::prelude::ColliderFlags)]>>::Output == (bevy::prelude::Entity, bevy_rapier2d::prelude::ColliderPosition, bevy_rapier2d::prelude::SharedShape, bevy_rapier2d::prelude::ColliderFlags)
--> src\pathfinding.rs:63:14 | 63 | .get(index.into()) | ^^^ cannot satisfy<_ as SliceIndex<[(bevy::prelude::Entity, bevy_rapier2d::prelude::ColliderPosition, bevy_rapier2d::prelude::SharedShape, bevy_rapier2d::prelude::ColliderFlags)]>>::Output == (bevy::prelude::Entity, bevy_rapier2d::prelude::ColliderPosition, bevy_rapier2d::prelude::SharedShape, bevy_rapier2d::prelude::ColliderFlags)
error[E0621]: explicit lifetime required in the type of
shape
--> src\pathfinding.rs:129:10 | 114 | shape: &dyn Shape, | ---------- help: add explicit lifetime'static
to the type ofshape
:&'static (dyn bevy_rapier2d::prelude::Shape + 'static)
... 129 | pool.spawn(async { | ^^^^^ lifetime'static
requirederror[E0621]: explicit lifetime required in the type of
query_pipeline
--> src\pathfinding.rs:129:10 | 112 | query_pipeline: &QueryPipeline, | -------------- help: add explicit lifetime'static
to the type ofquery_pipeline
:&'static bevy_rapier2d::prelude::QueryPipeline
... 129 | pool.spawn(async { | ^^^^^ lifetime'static
requiredThis is probably a more advanced use case, and I'm not sure what the plugin might do to make this easier. Maybe even an example of snapshotting collision data and accessing it in a pool would be useful? There are some obvious mistakes in my
Shapes
code--Rust Analyzer's automatic import added a few broken paths, for instance--but I feel like I'm adding mud to an existing mess rather than working toward a solution. Alternately, I'm not sure if there's a better solution to my pathfinding issue than taking physical shapes into account, but I had enough special cases for handling bad data that I thought it might help to prevent that bad data from being generated in the first place.Thanks.