Spew

crates.io docs.rs

A simple helper for spawning objects in Bevy.

Usage

First, create an enum that holds objects you might want to spawn:

rust enum Objects { Player, Monster, Coin, }

Think about which data you want to pass to the spawning function. In this example, we will specify a Transform for the new object. Next, add the plugin to your app, noting the two types we just mentioned:

```rust,ignore use spew::prelude::; use bevy::prelude::;

fn main() { App::build() // ... .add_plugin(SpewPlugin::::default()) // <--- Add the plugin // ... .run(); } ```

Now, we are ready to register our spawn functions. Each variant of the enum will be associated with its own spawn function that takes in a &mut World and the user provided data: ```rust,ignore use spew::prelude::; use bevy::prelude::;

fn main() { App::build() // ... .addspawners( // <--- Register the spawn functions (Objects::Player, spawnplayer), (Objects::Monster, spawnmonster), (Objects::Coin, spawncoin), ) // ... .run(); }

fn spawnplayer(world: &mut World, transform: Transform) { world.spawn(( Name::new("Spiffy the Adventurer"), TransformBundle::fromtransform(transform), )); }

fn spawnmonster(world: &mut World, transform: Transform) { world.spawn(( Name::new("Grumblor the Grumpy"), TransformBundle::fromtransform(transform), )); }

fn spawncoin(world: &mut World, transform: Transform) { world.spawn(( Name::new("$1000"), TransformBundle::fromtransform(transform), )); } ```

Finally, we can set our spawn functions to work by sending a SpawnEvent: ```rust,ignore use spew::prelude::; use bevy::prelude::;

fn main() { App::build() // ... .addsystem(setupmap.on_startup()) // ... .run(); }

fn setupmap(mut spawnevents: EventWriter>) { spawnevents.send(SpawnEvent::new( Objects::Player, Transform::fromxyz(0.0, 0.0, 0.0), )); spawnevents.send(SpawnEvent::new( Objects::Monster, Transform::fromxyz(5.0, 0.0, 0.0), )); spawnevents.send(SpawnEvent::new( Objects::Coin, Transform::fromxyz(10.0, 0.0, 0.0), )); } ```

You can read through the docs or peruse the examples for more use cases. Other cool stuff you can do is delay the spawning by a certain amount of frames or time or organize your spawn lists into multiple enums.

Compatibility

| bevy | spew | |------|------| | 0.10 | 0.1 |

Motivation

Bevy's Commands API allows you to spawn new entities with arbitrary components: ```rust use bevy::prelude::*;

fn spawnplayer(commands: &mut Commands) { commands.spawn(( Name::new("Adventurer"), TransformBundle::fromtransform(Transform::from_xyz(0.0, 0.0, 0.0)), )); } This works great! We can spawn more complex objects by just adding more components like assets: rust use std::f32::consts::TAU; use bevy::prelude::*;

fn spawnbullet(commands: &mut Commands, assetserver: Res) { commands.spawn(( Name::new("Bullet"), SceneBundle { scene: assetserver.load("models/bullet.gltf#Scene0"), transform: Transform { translation: Vec3::new(5.0, 4.0, 12.0), scale: Vec3::splat(0.012), rotation: Quat::fromrotationy(TAU / 2.), }, ..default() }, )); } but, in a real project, we would not spawn a bullet like that. The bullet would be spawned by a weapon at a certain translation. We might thus encapsulate the bullet spawning like this: rust,ignore use bevy::prelude::*; fn handleinput(...) { // ... if shouldfirebullet { let position = playertransform.translation; spawnbullet(&mut commands, &asset_server, position); } }

fn spawnbullet(commands: &mut Commands, assetserver: &AssetServer, position: Vec3) { commands.spawn(( Name::new("Bullet"), SceneBundle { scene: assetserver.load("models/bullet.gltf#Scene0"), transform: Transform { translation: position, scale: Vec3::splat(0.012), rotation: Quat::fromrotation_y(TAU / 2.), }, ..default() }, )); } ```

As you can see, this works but is quite ugly. handle_input has to pass around an asset server we might otherwise not even need in the system, and spawn_bullet has a jumble of seemingly unrelated parameters that will grow and grow over time. Growing parameter lists are not a problem when writing a system, but notice how here spawn_bullet is no longer a system but a helper function. Thus, its call will get longer and uglier over time, with all its parameters leaking into handle_input.

The solution to this is to move the spawning of the bullet into an own system that is accessed indirectly by handle_input via events, which is just what this crate helps you with! :)