Displaying the Level

Loading an asset is an asynchronous process. As it involves file or network access, it doesn't happen immediately. This is why the asset server is returning an Handle instead of the data.

Accessing the data from the Assets<T> resource returns an Option<T> as the data may not be present yet. In our case, we're using the 2 second delay of the splash screen to be sure that assets are done loading, so we can unwrap() the Option.

#![allow(unused)]
fn main() {
extern crate bevy;
use bevy::prelude::*;
#[derive(Asset, TypePath)]
struct Level {width: u32, height: u32, asteroids: u32, lives: u32}
#[derive(Resource)]
struct GameAssets {
}
#[derive(Resource)]
pub struct LoadedLevel { pub level: Handle<Level> }
#[derive(Component)]
struct Asteroid;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, States, Default)]
enum GameState { #[default] Game }
fn display_level(
    mut commands: Commands,
    game_assets: Res<GameAssets>,
    loaded_level: Res<LoadedLevel>,
    levels: Res<Assets<Level>>,
) {
    let level = levels.get(&loaded_level.level).unwrap();

    // do something with the level
}
}

Waiting for some time is not a good general solution to ensure assets are loaded: the actual delay will depend on the number of asset, the disk and CPU of the player.

There are different ways to go around that: you can poll assets in a system to check that they are available, you can wait for asset events or you can use a guard when loading assets.

A third party plugin that handles asset loading through states is bevy_asset_loader.