|
| 1 | +//! Shows how to generate and store assets at runtime. |
| 2 | +
|
| 3 | +use bevy::prelude::*; |
| 4 | + |
| 5 | +fn main() { |
| 6 | + App::new() |
| 7 | + .add_plugins(DefaultPlugins) |
| 8 | + .add_systems(Startup, setup) |
| 9 | + .add_systems(Update, generate_mesh_system.run_if(run_once)) |
| 10 | + .run(); |
| 11 | +} |
| 12 | + |
| 13 | +fn setup( |
| 14 | + mut commands: Commands, |
| 15 | + asset_server: Res<AssetServer>, |
| 16 | + mut materials: ResMut<Assets<StandardMaterial>>, |
| 17 | + meshes: Res<Assets<Mesh>>, |
| 18 | +) { |
| 19 | + commands.spawn((Camera3d::default(), Transform::from_xyz(0.0, 0.0, 5.0))); |
| 20 | + |
| 21 | + commands.spawn(( |
| 22 | + DirectionalLight::default(), |
| 23 | + Transform::default().looking_to(Dir3::new(Vec3::new(-1.0, -1.0, -1.0)).unwrap(), Dir3::Y), |
| 24 | + )); |
| 25 | + |
| 26 | + // The simplest way to generate an asset is to add it directly to the `Assets`. |
| 27 | + let material_handle = materials.add(StandardMaterial::default()); |
| 28 | + |
| 29 | + commands.spawn(( |
| 30 | + Transform::from_xyz(-2.0, 0.0, 0.0), |
| 31 | + MeshMaterial3d(material_handle.clone()), |
| 32 | + // Alternatively, `add_async` creates a task that runs your async function. Once it |
| 33 | + // completes, the asset is added to the `Assets`. This is "deferred" meaning that the asset |
| 34 | + // may take a frame to be added after the task completes. |
| 35 | + Mesh3d(asset_server.add_async(generate_mesh_async())), |
| 36 | + )); |
| 37 | + |
| 38 | + // The last way to generate assets is to reserve a handle, and then use `Assets::insert` to |
| 39 | + // populate the asset later. In this example, the `generate_mesh_system` system runs to populate |
| 40 | + // the mesh. |
| 41 | + let mesh_handle = meshes.reserve_handle(); |
| 42 | + commands.insert_resource(HandleToGenerate(mesh_handle.clone())); |
| 43 | + commands.spawn(( |
| 44 | + Transform::from_xyz(2.0, 0.0, 0.0) |
| 45 | + .with_rotation(Quat::from_rotation_x(50.0f32.to_radians())), |
| 46 | + Mesh3d(mesh_handle), |
| 47 | + MeshMaterial3d(material_handle), |
| 48 | + )); |
| 49 | +} |
| 50 | + |
| 51 | +async fn generate_mesh_async() -> Result<Mesh, std::io::Error> { |
| 52 | + // This mesh could take a while to generate. It could even take several frames (though in this |
| 53 | + // example it should be ~instant). |
| 54 | + |
| 55 | + Ok(Mesh::from(Cone::new(1.0, 2.0))) |
| 56 | +} |
| 57 | + |
| 58 | +#[derive(Resource)] |
| 59 | +struct HandleToGenerate(Handle<Mesh>); |
| 60 | + |
| 61 | +/// This system runs once to populate the handle in [`HandleToGenerate`]. |
| 62 | +/// |
| 63 | +/// This generates a runtime mesh. Since it's a system, it can use other data in the world to |
| 64 | +/// generate the asset! |
| 65 | +fn generate_mesh_system( |
| 66 | + handle_to_generate: Res<HandleToGenerate>, |
| 67 | + mut meshes: ResMut<Assets<Mesh>>, |
| 68 | +) { |
| 69 | + let mesh = Mesh::from(Torus::new(0.8, 1.2)); |
| 70 | + meshes.insert(&handle_to_generate.0, mesh).unwrap(); |
| 71 | +} |
0 commit comments