Skip to content

Commit

Permalink
feat: seek OnTargetNotFound
Browse files Browse the repository at this point in the history
  • Loading branch information
mrchantey committed Sep 27, 2024
1 parent 055c828 commit d0f261b
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 35 deletions.
2 changes: 1 addition & 1 deletion crates/beet_examples/src/scenes/ml/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn fetch_npc(mut commands: Commands) {
InsertOnTrigger::<OnRun, Velocity>::default()
.with_target(agent),
ContinueRun::default(),
Seek,
Seek::default(),
EndOnArrive::new(1.),
RemoveOnTrigger::<OnRunResult, SteerTarget>::default()
.with_target(agent),
Expand Down
2 changes: 1 addition & 1 deletion crates/beet_examples/src/scenes/spatial/seek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn seek(mut commands: Commands) {
RunOnAppReady::default(),
ContinueRun::default(),
TargetAgent(parent.parent_entity()),
Seek,
Seek::default(),
));
});
}
2 changes: 1 addition & 1 deletion crates/beet_examples/src/scenes/spatial/seek_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub fn seek_3d(mut commands: Commands) {
Name::new("Seek"),
ContinueRun::default(),
TargetAgent(agent),
Seek,
Seek::default(),
InsertOnTrigger::<OnRun, Velocity>::default()
.with_target(agent),
PlayAnimation::new(walk_index)
Expand Down
10 changes: 5 additions & 5 deletions crates/beet_spatial/src/steer/steer_actions/end_on_arrive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ impl EndOnArrive {

pub fn end_on_arrive(
mut commands: Commands,
agents: Query<(&Transform, &SteerTarget)>,
transforms: Query<&Transform>,
agents: Query<(&GlobalTransform, &SteerTarget)>,
transforms: Query<&GlobalTransform>,
mut query: Query<(Entity, &TargetAgent, &EndOnArrive), With<Running>>,
) {
for (entity, agent, action) in query.iter_mut() {
if let Ok((transform, target)) = agents.get(**agent) {
if let Ok(target) = target.position(&transforms) {
if Vec3::distance(transform.translation, target)
<= action.radius
if let Ok(target) = target.get_position(&transforms) {
if transform.translation().distance_squared(target)
<= action.radius.powi(2)
{
commands.entity(entity).trigger(OnRunResult::success());
}
Expand Down
76 changes: 57 additions & 19 deletions crates/beet_spatial/src/steer/steer_actions/seek.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,55 @@
use crate::prelude::*;
use beet_flow::prelude::*;
use bevy::prelude::*;
use forky::prelude::ResultTEExt;


/// Go to the agent's [`SteerTarget`] with an optional [`ArriveRadius`]
#[derive(Debug, Default, Clone, PartialEq, Component, Action, Reflect)]
#[reflect(Default, Component, ActionMeta)]
#[category(ActionCategory::Agent)]
#[systems(seek.in_set(TickSet))]
pub struct Seek;
pub struct Seek {
pub on_not_found: OnTargetNotFound,
}

impl Seek {
pub fn new(on_not_found: OnTargetNotFound) -> Self { Self { on_not_found } }
}


#[derive(Debug, Default, Clone, PartialEq, Reflect)]
pub enum OnTargetNotFound {
/// Warn
#[default]
Warn,
/// Remove the [`SteerTarget`]
Clear,
/// Remove the [`SteerTarget`] and emit [`OnRunResult::failure()`]
Fail,
/// Remove the [`SteerTarget`] and emit [`OnRunResult::success()`]
Succeed,
/// Do nothing
Ignore,
}


// TODO if target has Velocity, pursue
fn seek(
transforms: Query<&Transform>,
mut commands: Commands,
transforms: Query<&GlobalTransform>,
mut agents: Query<(
&Transform,
Entity,
&GlobalTransform,
&Velocity,
&SteerTarget,
&MaxSpeed,
&mut Impulse,
Option<&ArriveRadius>,
)>,
query: Query<(&TargetAgent, &Seek), With<Running>>,
query: Query<(Entity, &TargetAgent, &Seek), With<Running>>,
) {
for (target, _) in query.iter() {
for (entity, target, seek) in query.iter() {
if let Ok((
agent_entity,
transform,
velocity,
steer_target,
Expand All @@ -35,17 +59,31 @@ fn seek(
)) = agents.get_mut(**target)
// if agent has no steer_target thats ok
{
if let Some(target_position) = steer_target
.position(&transforms)
.ok_or(|e| log::warn!("{e}"))
{
*impulse = seek_impulse(
&transform.translation,
&velocity,
&target_position,
*max_speed,
arrive_radius.copied(),
);
match (&seek.on_not_found, steer_target.get_position(&transforms)) {
(_, Ok(target_position)) => {
*impulse = seek_impulse(
&transform.translation(),
&velocity,
&target_position,
*max_speed,
arrive_radius.copied(),
);
}
(OnTargetNotFound::Clear, Err(_)) => {
commands.entity(agent_entity).remove::<SteerTarget>();
}
(OnTargetNotFound::Fail, Err(_)) => {
commands.entity(agent_entity).remove::<SteerTarget>();
commands.entity(entity).trigger(OnRunResult::failure());
}
(OnTargetNotFound::Succeed, Err(_)) => {
commands.entity(agent_entity).remove::<SteerTarget>();
commands.entity(entity).trigger(OnRunResult::success());
}
(OnTargetNotFound::Ignore, Err(_)) => {}
(OnTargetNotFound::Warn, Err(msg)) => {
log::warn!("{}", msg);
}
}
}
}
Expand Down Expand Up @@ -78,7 +116,7 @@ mod test {
parent.spawn((
TargetAgent(parent.parent_entity()),
Running,
Seek,
Seek::default(),
));
})
.id();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,21 @@ impl Default for SteerTargetScoreProvider {
fn provide_score(
trigger: Trigger<RequestScore>,
mut commands: Commands,
transforms: Query<&Transform>,
agents: Query<(&Transform, &SteerTarget)>,
transforms: Query<&GlobalTransform>,
agents: Query<(&GlobalTransform, &SteerTarget)>,
query: Query<(&SteerTargetScoreProvider, &TargetAgent, &Parent)>,
) {
let (action, agent, parent) = query
.get(trigger.entity())
.expect(expect_action::ACTION_QUERY_MISSING);

let score = if let Ok((transform, target)) = agents.get(**agent)
&& let Ok(target) = target.position(&transforms)
&& let Ok(target) = target.get_position(&transforms)
{
let dist = Vec3::distance(transform.translation, target);
if dist >= action.min_radius && dist <= action.max_radius {
let dist = transform.translation().distance_squared(target);
if dist >= action.min_radius.powi(2)
&& dist <= action.max_radius.powi(2)
{
1.
} else {
0.
Expand Down
8 changes: 5 additions & 3 deletions crates/beet_spatial/src/steer/steer_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ impl Default for SteerTarget {
}

impl SteerTarget {
/// Get either the fixed position or the entity's transform, dependent on the variant.
pub fn position(&self, query: &Query<&Transform>) -> Result<Vec3> {
/// Get either the fixed position or the entity's `Transform.translation`, dependent on the variant.
/// # Errors
/// If the variant is `SteerTarget::Entity` and no `Transform` could be found.
pub fn get_position(&self, query: &Query<&GlobalTransform>) -> Result<Vec3> {
match self {
Self::Position(position) => Ok(*position),
Self::Entity(entity) => {
if let Ok(transform) = query.get(*entity) {
Ok(transform.translation)
Ok(transform.translation())
} else {
anyhow::bail!("transform not found for entity {entity:?}")
}
Expand Down

0 comments on commit d0f261b

Please sign in to comment.