Bevy Version: | 0.14 | (current) |
---|
The App
Relevant official examples: All of them ;)
In particular, check out the complete game examples:
alien_cake_addict
,
breakout
.
To enter the Bevy runtime, you need to configure an App
. The app is how you
define the structure of all the things that make up your project:
plugins, systems (and their configuration/metadata:
run conditions, ordering, sets),
event types, states, schedules…
You typically create your App
in your project's main
function. However,
you don't have to add everything from there. If you want to add things to your
app from multiple places (like other Rust files or crates), use
plugins. As your project grows, you will need to do that to keep
everything organized.
fn main() {
App::new()
// Bevy itself:
.add_plugins(DefaultPlugins)
// Plugins from our game/project:
.add_plugins(ui::MyUiPlugin)
// events:
.add_event::<LevelUpEvent>()
// systems to run once at startup:
.add_systems(Startup, spawn_things)
// systems to run each frame:
.add_systems(Update, (
camera_follow_player,
debug_levelups,
debug_stats_change,
))
// ...
// launch the app!
.run();
}
Note: use tuples with add_systems
/add_plugins
/configure_sets
to add
multiple things at once.
Component types do not need to be registered.
Schedules cannot (yet) be modified at runtime; all systems you
want to run must be added/configured in the App
ahead of time. You can
control individual systems using run conditions. You can also
dynamically enable/disable entire schedules using the MainScheduleOrder
resource.
Builtin Bevy Functionality
The Bevy game engine's own functionality is represented as a plugin group. Every typical Bevy app must first add it, using either:
DefaultPlugins
if you are making a full game/app.MinimalPlugins
for something like a headless server.
Setting up data
Normally, you can set up your data from systems. Use Commands from regular systems, or use exclusive systems to get full World access.
Add your setup systems to the Startup
schedule for
things you want to initialize at launch, or use state enter/exit
systems to do things when transitioning between menus, game modes, levels, etc.
However, you can also initialize data directly from the app builder. This is common for resources, if they need to be present at all times. You can also get direct World access.
// Create (or overwrite) resource with specific value
app.insert_resource(StartingLevel(3));
// Ensure resource exists; if not, create it
// (using `Default` or `FromWorld`)
app.init_resource::<MyFancyResource>();
// We can also access/manipulate the World directly
// (in this example, to spawn an entity, but you can do anything)
app.world_mut().spawn(SomeBundle::default());
Quitting the App
To cleanly shut down bevy, send an AppExit
event from any
system:
use bevy::app::AppExit;
fn exit_system(mut exit: EventWriter<AppExit>) {
exit.send(AppExit::Success);
}
In a real app, you could do this from various places, such as a handler for an "Exit" button in your main menu, etc.
You can specify the exit code to return to the OS. If Bevy receives
multiple AppExit
events, success will only be returned if all
of them report success. If some report an error, the last event will
determine the actual exit code of the process.