| Crates.io | bevy_enum_event |
| lib.rs | bevy_enum_event |
| version | 0.3.2 |
| created_at | 2025-10-20 20:01:10.5188+00 |
| updated_at | 2026-01-22 13:30:52.141731+00 |
| description | Derive macros for Bevy event and message types - generates Event, Message, and EntityEvent types from enum variants with support for triggers, observers, buffered messaging, and entity propagation |
| homepage | |
| repository | https://github.com/ffmulks/bevy_enum_event |
| max_upload_size | |
| id | 1892663 |
| size | 175,262 |
Derive macros that generate Bevy event and message types from enum variants.
Transform enum variants into distinct Bevy event/message structs automatically. Each variant becomes a separate type in a snake_case module, eliminating boilerplate while preserving type safety.
use bevy::prelude::*;
use bevy_enum_event::EnumEvent;
#[derive(EnumEvent, Clone)]
enum GameEvent {
Victory(String),
ScoreChanged { team: u32, score: i32 },
GameOver,
}
// Generates: game_event::Victory, game_event::ScoreChanged, game_event::GameOver
| Bevy | bevy_enum_event |
|---|---|
| 0.18 | 0.3 |
| 0.17 | 0.2 |
| 0.16 | 0.1 |
[dependencies]
bevy_enum_event = "0.3.2"
Bevy 0.17+ distinguishes between three event/message types:
EnumEvent - Observer-based global events (triggered via world.trigger())EnumEntityEvent - Entity-targeted observer events with optional propagationEnumMessage - Buffered messages (written via MessageWriter, read via MessageReader)For observer-based events that are triggered globally and handled by observers.
use bevy_enum_event::EnumEvent;
#[derive(EnumEvent, Clone)]
enum PlayerState {
Idle, // Unit variant
Moving(f32), // Tuple variant
Attacking { target: Entity }, // Named field variant
}
fn setup(mut app: App) {
app.add_observer(on_attacking);
}
fn on_attacking(event: On<player_state::Attacking>) {
println!("Attacking {:?}", event.target);
}
// Trigger the event
fn trigger_attack(mut commands: Commands) {
commands.trigger(player_state::Attacking { target: Entity::PLACEHOLDER });
}
Single-field variants automatically implement Deref/DerefMut:
#[derive(EnumEvent, Clone)]
enum NetworkEvent {
MessageReceived(String), // Automatic deref to String
}
fn on_message(msg: On<network_event::MessageReceived>) {
let content: &String = &**msg;
}
For multi-field variants, mark one field with #[enum_event(deref)]:
#[derive(EnumEvent, Clone)]
enum GameEvent {
PlayerScored {
#[enum_event(deref)]
player: Entity,
points: u32
},
}
Disable with default-features = false.
For buffered messages that are written/read between systems using MessageWriter/MessageReader.
Important: Each message type must be registered with app.add_message::<T>().
use bevy::prelude::*;
use bevy_enum_event::EnumMessage;
#[derive(EnumMessage, Clone)]
enum NetworkCommand {
Connect { address: String },
Disconnect,
SendData(Vec<u8>),
}
fn setup(app: &mut App) {
// REQUIRED: Register message types
app.add_message::<network_command::Connect>();
app.add_message::<network_command::Disconnect>();
app.add_message::<network_command::SendData>();
}
fn send_commands(mut writer: MessageWriter<network_command::Connect>) {
writer.write(network_command::Connect {
address: "127.0.0.1:8080".to_string(),
});
}
fn receive_commands(mut reader: MessageReader<network_command::Connect>) {
for cmd in reader.read() {
println!("Connecting to {}", cmd.address);
}
}
Entity-targeted events that trigger entity-specific observers.
{ field: Type } syntax)entity: Entity field or #[enum_event(target)] on a custom fielduse bevy::prelude::*;
use bevy_enum_event::EnumEntityEvent;
#[derive(EnumEntityEvent, Clone, Copy)]
enum PlayerEvent {
Spawned { entity: Entity },
Damaged { entity: Entity, amount: f32 },
}
// Entity-specific observer
fn setup(mut commands: Commands) {
commands.spawn_empty().observe(|damaged: On<player_event::Damaged>| {
println!("This player took {} damage", damaged.amount);
});
}
#[derive(EnumEntityEvent, Clone, Copy)]
enum CombatEvent {
Attack {
#[enum_event(target)]
attacker: Entity,
defender: Entity,
},
}
Events can bubble up entity hierarchies:
// Basic propagation (uses ChildOf)
#[derive(EnumEntityEvent, Clone, Copy)]
#[enum_event(propagate)]
enum UiEvent {
Click { entity: Entity },
}
// Auto propagation (always bubbles)
#[derive(EnumEntityEvent, Clone, Copy)]
#[enum_event(auto_propagate, propagate)]
enum SystemEvent {
Update { entity: Entity },
}
// Custom relationship
#[derive(EnumEntityEvent, Clone, Copy)]
#[enum_event(propagate = &'static ::bevy::prelude::ChildOf)]
enum CustomEvent {
Action { entity: Entity },
}
Control propagation in observers:
fn on_click(mut click: On<ui_event::Click>) {
click.propagate(true); // Continue bubbling
let original = click.original_event_target();
}
Override enum-level settings per variant:
#[derive(EnumEntityEvent, Clone, Copy)]
#[enum_event(propagate)]
enum MixedEvent {
Normal { entity: Entity }, // Uses enum-level
#[enum_event(auto_propagate, propagate)]
AutoEvent { entity: Entity }, // Overrides with auto
}
Full support for generic parameters and lifetimes:
#[derive(EnumEvent, Clone)]
enum GenericEvent<'a, T>
where
T: Clone + 'a,
{
Borrowed(&'a T),
Owned(T),
Done,
}
| Pattern | Macro | Use Case |
|---|---|---|
| Global triggers + observers | EnumEvent |
Game events, UI notifications, state changes |
| Buffered inter-system communication | EnumMessage |
Network commands, async results, command queues |
| Entity-targeted observers | EnumEntityEvent |
Entity interactions, damage systems, component events |
MIT OR Apache-2.0