Bevy Worlds
A World
is what holds the state of our App
.
We store all our components, entities and resources inside this struct.
Most of the APIs you use eventually mutate this struct 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
.
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.
We don't really have to think about managing the World
manually. Usually this is done invisibly for us when we use commands, or read from events.
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);
// ....
}