Tainted\\Coders

Bevy Worlds

Bevy version: 0.14Last updated:

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);

  // ....
}