//! This example demonstrates how to load scene data from files and then dynamically //! apply that data to entities in your Bevy `World`. This includes spawning new //! entities and applying updates to existing ones. Scenes in Bevy encapsulate //! serialized and deserialized `Components` or `Resources` so that you can easily //! store, load, and manipulate data outside of a purely code-driven context. //! //! This example also shows how to do the following: //! * Register your custom types for reflection, which allows them to be serialized, //! deserialized, and manipulated dynamically. //! * Skip serialization of fields you don't want stored in your scene files (like //! runtime values that should always be computed dynamically). //! * Save a new scene to disk to show how it can be updated compared to the original //! scene file (and how that updated scene file might then be used later on). //! //! The example proceeds by creating components and resources, registering their types, //! loading a scene from a file, logging when changes are detected, and finally saving //! a new scene file to disk. This is useful for anyone wanting to see how to integrate //! file-based scene workflows into their Bevy projects. //! //! # Note on working with files //! //! The saving behavior uses the standard filesystem APIs, which are blocking, so it //! utilizes a thread pool (`IoTaskPool`) to avoid stalling the main thread. This //! won't work on WASM because WASM typically doesn't have direct filesystem access. //! use bevy::{asset::LoadState, prelude::*, tasks::IoTaskPool}; use core::time::Duration; use std::{fs::File, io::Write}; /// The entry point of our Bevy app. /// /// Sets up default plugins, registers all necessary component/resource types /// for serialization/reflection, and runs the various systems in the correct schedule. fn main() { App::new() .add_plugins(DefaultPlugins) .register_type::() .register_type::() .register_type::() .add_systems( Startup, (save_scene_system, load_scene_system, infotext_system), ) .add_systems(Update, (log_system, panic_on_fail)) .run(); } /// # Components, Resources, and Reflection /// /// Below are some simple examples of how to define your own Bevy `Component` types /// and `Resource` types so that they can be properly reflected, serialized, and /// deserialized. The `#[derive(Reflect)]` macro enables Bevy's reflection features, /// and we add component-specific reflection by using `#[reflect(Component)]`. /// We also illustrate how to skip serializing fields and how `FromWorld` can help /// create runtime-initialized data. /// /// A sample component that is fully serializable. /// /// This component has public `x` and `y` fields that will be included in /// the scene files. Notice how it derives `Default`, `Reflect`, and declares /// itself as a reflected component with `#[reflect(Component)]`. #[derive(Component, Reflect, Default)] #[reflect(Component)] // this tells the reflect derive to also reflect component behaviors struct ComponentA { /// An example `f32` field pub x: f32, /// Another example `f32` field pub y: f32, } /// A sample component that includes both serializable and non-serializable fields. /// /// This is useful for skipping serialization of runtime data or fields you /// don't want written to scene files. #[derive(Component, Reflect)] #[reflect(Component)] struct ComponentB { /// A string field that will be serialized. pub value: String, /// A `Duration` field that should never be serialized to the scene file, so we skip it. #[reflect(skip_serializing)] pub _time_since_startup: Duration, } /// This implements `FromWorld` for `ComponentB`, letting us initialize runtime fields /// by accessing the current ECS resources. In this case, we acquire the `Time` resource /// and store the current elapsed time. impl FromWorld for ComponentB { fn from_world(world: &mut World) -> Self { let time = world.resource::