This repository was archived by the owner on Oct 7, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 82
This repository was archived by the owner on Oct 7, 2025. It is now read-only.
Alt design pattern with In Out Systems #90
Copy link
Copy link
Open
Description
Hiyo ! I was playing around with other possible patterns - mostly out of curiosity and as a learning experience and was recently reading a one shot systems related PR and thought that'd be cool. Anyways, here's how I'd think it'd make sense as a utility ai architecture
pub struct BrainPlugin;
impl Plugin for BrainPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup)
.add_systems(Update, (decide_best_action, sleepiness_tick));
}
}
#[derive(Component)]
pub struct Thinker;
#[derive(Component)]
pub struct Sleepiness(f32);
#[derive(Bundle)]
pub struct MyActorBundle {
pub thinker: Thinker,
pub considerations: Considerations,
pub action_state: ActionState,
pub sleepiness: Sleepiness,
}
#[derive(Component)]
pub struct Considerations {
pub considerations: Vec<Consideration>,
}
#[derive(Component)]
pub enum ActionState {
Idle,
Executing,
Done,
}
pub struct Consideration {
pub name: String,
pub scorer: SystemId<Entity, f32>,
pub action: SystemId<ActionState, ActionState>,
}
fn my_sleep_scorer(In(entity): In<Entity>, sleepiness: Query<&Sleepiness>) -> f32 {
let sleepiness = sleepiness.get(entity).unwrap();
sleepiness.0 / 100.0
}
fn sleep(In(action_state): In<ActionState>) -> ActionState {
todo!();
}
fn decide_best_action(world: &mut World) {
let mut highest_consideration: Option<&Consideration> = None;
let mut highest_score = 0.0;
let mut query = world.query::<(Entity, &Considerations)>();
for (actor_entity, considerations) in query.iter(world) {
for consideration in &considerations.considerations {
// This doesn't compile because of multiple borrows :(
let Ok(score) = world.run_system_with_input(consideration.scorer, actor_entity) else {
continue;
};
if score > highest_score {
highest_consideration = Some(consideration);
highest_score = score;
}
}
}
if let Some(consideration) = highest_consideration {
let Ok(next) = world.run_system_with_input(consideration.action, ActionState::Idle) else {
return;
};
todo!("set next action state");
}
}
fn setup(world: &mut World) {
let scorer = world.register_system(my_sleep_scorer);
let action = world.register_system(sleep);
world.spawn(MyActorBundle {
thinker: Thinker,
action_state: ActionState::Idle,
considerations: Considerations {
considerations: vec![Consideration {
name: "Sleep".into(),
scorer: scorer,
action: action,
}],
},
sleepiness: Sleepiness(0.0),
});
}
fn sleepiness_tick(mut sleepiness: Query<&mut Sleepiness>) {
for mut sleepiness in sleepiness.iter_mut() {
sleepiness.0 += 1.0;
}
}I hope you find this interesting ! I thought so and just wanted to share so I could hear your opinion on it :D
I'm a big rust noob so this might be totally wrong/absurd
(also sorry if this was better suited as a discussion ! lol)
Metadata
Metadata
Assignees
Labels
No labels