Hi, I am pretty new to bevy and I am wondering if I can send signals to specific entities.
Like if I have a grid of entities and would like for each of them to send a signal to their neighbors. If every entity had an Vec of their neighbors addresses (lik UUIDs?) could It send Information to it’s next, or is there another way of doing such things in bevy.
#Send signals to specific entities
1 messages · Page 1 of 1 (latest)
One thing you could do is set it up so the entities in the grid each have a Vec of Entity (the neighbors) and then use events (https://github.com/bevyengine/bevy/blob/release-0.11.3/examples/ecs/event.rs) to send information to the neighbors
Your Event would contain Entity + the information you want to send
Then add a query for the entities in the grid to your eventlistener, so you can do something like let entity_or_components_we_want_to_affect = grid_query.get(my_event.source_entity)
This sounds a bit anti-ECS, entities are just IDs so how are they going to receive signals?
Yea, I only programmed non ecs games and was wondering how to do this the ecs style
It has to happen in a system somehow. An entity could store its neighbouring entities in a MyComponentName<Vec<Entity>> component. then a system can read that and any other data it might need to perform the operation you want to happen, and perform that operation
or you could have a resource storing neighbours, I do that in my jigsaw, dunno if it's better
wait, no, I switched to the first model I remember now because I had to keep merging neighbours
So I have an Entity, that has an Vec of Entities(neighbors), A query that for every entity,let’a this entity send a signal to its stored Entities(neighbors).
No, an entity can't recive an signal only systems can
There is no signal here, the system can just apply whatever behaviour the signal is supposed to trigger. if you do want it more indirectly, maybe each entity can have some other component to store these "signals" but it all depends on what exactly you're doing which I don't know
a system would still be applying the information to these other components
Oh, yea, since the system isn't the enities system, but sort of an global on it can apply the change directly.
Often times storing the events is clearner, especially if you have multiple causes for the events or multiple things that they trigger
Generally one-to-many and many-to-many things benefit from storing stuff on the entities
So I would like to a little game where gras Blocks are spawend an you have to eat the gras, every timer, every eaten gras looks if it's neighbours has gras on it, if so I grows gras again.
Sounds like a spread grass system that looks at tiles, and if they have no grass, iterates over neighbours to find if any have grass, then mutates some has grass conponent to be true
Store neighbors in a component, loop through blocks, for each block loop through neighbors
I'd probably add some components to distinguish between blocks with grass and without, could just be an empty struct (marker)
And then have two queries, one for those with grass and one for those without. Without grass query also contains the neighbor component
And then do something like if neighbors.iter().any(|e| grass_query.get(e).is_ok()) {/* regrow logic */ }
That way you also only iterate the blocks without grass and don't waste time on the ones that don't need to think about regrowing
And this specific approach also gets around the annoying fact that the iteration direction could matter
Thanks, how could I get an vec of entities, I would spawn blocks like this:
pub fn spawn_blocks( mut commands: Commands, window_query: Query<&Window, With<PrimaryWindow>>, asset_server: Res<AssetServer>, ) { let window = window_query.get_single().unwrap(); let x_max: usize = 3; let y_max: usize = 3; for x in 0..x_max { for y in 0..y_max { commands.spawn(( SpriteBundle { transform: Transform::from_xyz( window.width() / 2.0 + (x as f32 * TEXTURESIZE), window.height() / 2.0 + (y as f32 * TEXTURESIZE), 0.0, ), texture: asset_server.load("sprites/Gras.png"), ..default() }, EnviromentBlock { location: Vec2 { x: x as f32, y: y as f32, }, block: components::Block::Gras, }, )); } } }
you could, as you spawn them, store the entities in a hashmap with (x, y) keys and entity values
then use that to loop again and apply neighbours
If you use three backticks ` on either side, it gives you a code block that looks like this:
pub fn spawn_blocks(
mut commands: Commands,
window_query: Query<&Window, With<PrimaryWindow>>,
asset_server: Res<AssetServer>,
) {
let window = window_query.get_single().unwrap();
let x_max: usize = 3;
let y_max: usize = 3;
for x in 0..x_max {
for y in 0..y_max {
commands.spawn((
SpriteBundle {
transform: Transform::from_xyz(
window.width() / 2.0 + (x as f32 * TEXTURESIZE),
window.height() / 2.0 + (y as f32 * TEXTURESIZE),
0.0,
),
texture: asset_server.load("sprites/Gras.png"),
..default()
},
EnviromentBlock {
location: Vec2 {
x: x as f32,
y: y as f32,
},
block: components::Block::Gras,
},
));
}
}
}
And if you put rs or rust after the first three it gives you syntax highlighting
Also hardly relevant but in general it's easier to adjust camera viewport size than to resize the sprites like that.
You could just choose that your view area is a certain size like 10 by 10 and set the camera to render that
By default 1 unit in the world gets rendered as 1 pixel I believe
But yeah what Haddock said