error_handling/
error_handling.rs1use bevy::ecs::{error::warn, world::DeferredWorld};
5use bevy::math::sampling::UniformMeshSampler;
6use bevy::prelude::*;
7
8use rand::distr::Distribution;
9use rand::SeedableRng;
10use rand_chacha::ChaCha8Rng;
11
12fn main() {
13 let mut app = App::new();
14 app.set_error_handler(warn);
22
23 app.add_plugins(DefaultPlugins);
24
25 #[cfg(feature = "bevy_mesh_picking_backend")]
26 app.add_plugins(MeshPickingPlugin);
27
28 app.add_systems(Startup, setup);
32
33 app.add_systems(Startup, failing_commands);
36
37 app.add_systems(
39 PostStartup,
40 failing_system.pipe(|result: In<Result>| {
41 let _ = result.0.inspect_err(|err| info!("captured error: {err}"));
42 }),
43 );
44
45 app.add_observer(fallible_observer);
47
48 app.run();
54}
55
56fn setup(
60 mut commands: Commands,
61 mut meshes: ResMut<Assets<Mesh>>,
62 mut materials: ResMut<Assets<StandardMaterial>>,
63) -> Result {
64 let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
65
66 commands.spawn((
68 Mesh3d(meshes.add(Plane3d::default().mesh().size(12.0, 12.0))),
69 MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
70 Transform::from_xyz(0.0, -2.5, 0.0),
71 ));
72
73 commands.spawn((
75 PointLight {
76 shadows_enabled: true,
77 ..default()
78 },
79 Transform::from_xyz(4.0, 8.0, 4.0),
80 ));
81
82 commands.spawn((
84 Camera3d::default(),
85 Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
86 ));
87
88 let mut sphere_mesh = Sphere::new(1.0).mesh().ico(7)?;
90 sphere_mesh.generate_tangents()?;
91
92 let mut sphere = commands.spawn((
94 Mesh3d(meshes.add(sphere_mesh.clone())),
95 MeshMaterial3d(materials.add(StandardMaterial::default())),
96 Transform::from_xyz(-1.0, 1.0, 0.0),
97 ));
98
99 let triangles = sphere_mesh.triangles()?;
101 let distribution = UniformMeshSampler::try_new(triangles)?;
102
103 let point_mesh = meshes.add(Sphere::new(0.01).mesh().ico(3)?);
105 let point_material = materials.add(StandardMaterial {
106 base_color: Srgba::RED.into(),
107 emissive: LinearRgba::rgb(1.0, 0.0, 0.0),
108 ..default()
109 });
110
111 for point in distribution.sample_iter(&mut seeded_rng).take(10000) {
113 sphere.with_child((
114 Mesh3d(point_mesh.clone()),
115 MeshMaterial3d(point_material.clone()),
116 Transform::from_translation(point),
117 ));
118 }
119
120 Ok(())
122}
123
124fn fallible_observer(
126 pointer_move: On<Pointer<Move>>,
127 mut world: DeferredWorld,
128 mut step: Local<f32>,
129) -> Result {
130 let mut transform = world
131 .get_mut::<Transform>(pointer_move.entity)
132 .ok_or("No transform found.")?;
133
134 *step = if transform.translation.x > 3. {
135 -0.1
136 } else if transform.translation.x < -3. || *step == 0. {
137 0.1
138 } else {
139 *step
140 };
141
142 transform.translation.x += *step;
143
144 Ok(())
145}
146
147#[derive(Resource)]
148struct UninitializedResource;
149
150fn failing_system(world: &mut World) -> Result {
151 world
152 .get_resource::<UninitializedResource>()
155 .ok_or("Resource not initialized")?;
157
158 Ok(())
159}
160
161fn failing_commands(mut commands: Commands) {
162 commands
163 .entity(Entity::from_raw_u32(12345678).unwrap())
165 .insert(Transform::default());
169
170 commands.queue_handled(
173 |world: &mut World| -> Result {
174 world
175 .get_resource::<UninitializedResource>()
176 .ok_or("Resource not initialized when accessed in a command")?;
177
178 Ok(())
179 },
180 |error, context| {
181 error!("{error}, {context}");
182 },
183 );
184}