You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bevy Events are a nice mechanism to fan-out notifications about things that happen in one system to many other systems. One trigger system takes a &mut EventWriter and many other systems take an &EventReader, and can listen for updates. They don't work well for events that get triggered by many systems but consumed by few because systems with an EventWriter cannot run in parallel.
Examples where bevy's Events work well are things like a player leveling up, which is triggered by one level_up() system, and then other systems like an audio effects system, a UI update system, ... can listen to that and handle it. Systems reading events can all run in parallel, but systems writing events cannot run in parallel.
I've found that in my code, the dependencies are usually the other way round. Instead of the audio plugin knowing about and depending on the player plugin, the player plugin depends on the audio plugin. The audio system doesn't wait for a PlayerLevelUp event to then trigger a sound, but it waits for a PlayAudioEffect event that can be triggered by many different systems for different audio effects. Or another example, for an enemy attack, I don't have an enemy system trigger an EnemyAttack event and then an audio effect system and a animation system both listen to that and play a sound or start an animation respectively, but I have an audio system listen for PlayAudioEffect events and an animation system listen to PlayAnimation events, and the enemy system triggers both of those.
I'm not sure if ordering dependencies this direction or the other direction is better from an architectural point of view (arguments and opinions welcome), but let's for now assume that ordering dependencies in this way is something Bevy would like to make easy.
This scenario means you have many event writers that can trigger an event like an audio effect and only one event reader that then plays the list of triggered events. Those writers should ideally be able to run in parallel, since the only resource they share is that they all might trigger an audio effect. It's similar to a mpsc (multi producer single consumer) channel, while bevy events are more like a spmc channel. Systems writing events should be able to run in parallel while systems reading events can be mutually exclusive. I'm proposing Bevy add support for mpsc events.
A trivial implementation could be built around mpsc::channel:
But maybe we can actually do something more efficient, similar to how bevy's spmc events are lock free. Maybe each writing system could have their own &mut Vec to write to and the reading system would get mutable access to them all.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Bevy Events are a nice mechanism to fan-out notifications about things that happen in one system to many other systems. One trigger system takes a
&mut EventWriter
and many other systems take an&EventReader
, and can listen for updates. They don't work well for events that get triggered by many systems but consumed by few because systems with anEventWriter
cannot run in parallel.Examples where bevy's Events work well are things like a player leveling up, which is triggered by one
level_up()
system, and then other systems like an audio effects system, a UI update system, ... can listen to that and handle it. Systems reading events can all run in parallel, but systems writing events cannot run in parallel.I've found that in my code, the dependencies are usually the other way round. Instead of the audio plugin knowing about and depending on the player plugin, the player plugin depends on the audio plugin. The audio system doesn't wait for a
PlayerLevelUp
event to then trigger a sound, but it waits for aPlayAudioEffect
event that can be triggered by many different systems for different audio effects. Or another example, for an enemy attack, I don't have an enemy system trigger anEnemyAttack
event and then an audio effect system and a animation system both listen to that and play a sound or start an animation respectively, but I have an audio system listen forPlayAudioEffect
events and an animation system listen toPlayAnimation
events, and the enemy system triggers both of those.I'm not sure if ordering dependencies this direction or the other direction is better from an architectural point of view (arguments and opinions welcome), but let's for now assume that ordering dependencies in this way is something Bevy would like to make easy.
This scenario means you have many event writers that can trigger an event like an audio effect and only one event reader that then plays the list of triggered events. Those writers should ideally be able to run in parallel, since the only resource they share is that they all might trigger an audio effect. It's similar to a mpsc (multi producer single consumer) channel, while bevy events are more like a spmc channel. Systems writing events should be able to run in parallel while systems reading events can be mutually exclusive. I'm proposing Bevy add support for mpsc events.
A trivial implementation could be built around mpsc::channel:
But maybe we can actually do something more efficient, similar to how bevy's spmc events are lock free. Maybe each writing system could have their own
&mut Vec
to write to and the reading system would get mutable access to them all.Beta Was this translation helpful? Give feedback.
All reactions