Bevy Worlds
A World
is what holds the state of our App
. It contains all the entities, components, and resources.
Most of the APIs like queries and commands eventually mutate this storage somewhere underneath.
In fact, when you are modifying the App
in your main function, you are really modifying the underlying game World
:
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// This will call `register_system` on our `World`
.add_systems(Update, hello_world)
.run();
}
Doing so manually with a World
itself would look like:
let mut world = World::new();
world.add_plugin(DefaultPlugins);
world.register_system(hello_world)
The only thing really unique to App
here is the App::run
method. The whole game loop is the responsibility of the App
but everything else goes onto the World
.
The reason why the World
is usually hidden from you is because Bevy is trying to run all our systems in parallel. If we had each system manipulating the world directly then none of them could run at the same time.
This is why when you execute commands, they are scheduled to run in a specific system that will hand over exclusive mutable access so each command can mutate our game's state independently all at once.
Creating a world
Normally we have a World
created for us when we App::new()
, but there are many circumstances where we might want to create a new one.
For example, during testing its common to create a fresh world that you set up to test a specific plugin or function:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_world() {
let mut world = World::new();
// Set up and test the world
}
}
Once you create a World
it is assigned a WorldId
which lets Bevy figure out whether or not your systems need exclusive access to the same SystemParam
.
Another example is when we load or save in scenes. Loading a scene means deserializing a scene file into some existing World
:
fn save_scene_system(world: &mut World) {
let mut scene_world = World::new();
let type_registry = world.resource::<AppTypeRegistry>().clone();
scene_world.insert_resource(type_registry);
let scene = DynamicScene::from_world(&scene_world);
// ....
}