Hot‑Reloading Assets in Bevy: Setup, Benefits, and Limits
Learn how Bevy’s AssetServer watches files and updates handles at runtime, see a sprite demo, and understand the trade‑offs between debug and release builds.
16 Dec 2025, 10:08 UTC

Problem: Waiting for a rebuild to see a texture change
When iterating on game art, you often edit a PNG, save it, and then restart the binary to see the update. That restart breaks flow and wastes time, especially when tweaking colors or shader constants.
Thesis
Bevy’s AssetServer plugin provides automatic hot‑reloading for any asset that implements the Asset trait. In a debug build you get instant updates without restarting, while release builds strip the watcher for zero overhead.
Setting up a minimal sprite demo
- Create a new project and add Bevy:
- Add a PNG asset (e.g.,
assets/sprite.png) to the project root. - Replace the generated
src/main.rswith the following code: - Run the debug build:
# Run in a terminal with normal user permissions
cargo new bevy_hotreload && cd bevy_hotreload
cargo add bevy
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_startup_system(setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res) {
commands.spawn(Camera2dBundle::default());
commands.spawn(SpriteBundle {
texture: asset_server.load("sprite.png"),
transform: Transform::from_xyz(0.0, 0.0, 0.0),
..default()
});
}
cargo run
You should see a window displaying the sprite. Keep the program running.
Observing hot reload in action
While the binary is still executing, open sprite.png in an external image editor (e.g., GIMP, Photoshop, or even a simple paint program). Make a visible change — such as drawing a bright spot — and save the file.
Bevy’s AssetServer spawns a file‑watcher thread that uses the OS’s native notification system (inotify on Linux, kqueue on macOS, ReadDirectoryChangesW on Windows). When the file changes, the watcher notifies the AssetServer, which reloads the asset and updates all existing Handle<Texture> instances. The sprite on screen should update instantly, showing your edit without a restart.
How to verify: Look for the visual change immediately after saving. If you do not see it, check that you are running a debug build (the default cargo run) and that the file watcher is active on your platform.
Trade‑offs and limitations
- Performance cost: The watcher thread and polling fallback add a small runtime overhead. In most desktop debug builds this is negligible, but on battery‑constrained devices you may notice increased CPU usage.
- Platform fallbacks: On Windows configurations lacking proper directory‑change notifications (e.g., some network drives or older Windows versions), Bevy falls back to polling every few hundred milliseconds, which can increase latency.
- Release builds: The
AssetServerplugin is compiled out entirely when building with--release. Consequently, hot reloading does not work, and you must restart to see asset changes. This ensures deterministic performance but means you cannot rely on hot‑reloading for production‑like testing. - Asset validity: If you save a corrupted or incomplete file, the reload may fail, causing a temporary missing texture or a panic if the asset type does not handle errors gracefully. Always ensure the asset is valid before saving.
- Custom assets: For assets that own GPU resources (e.g., custom meshes or render targets), you must implement the
Assettrait’sreloadmethod to recreate those resources; otherwise stale handles can lead to crashes.
Actionable closing
To leverage hot reloading effectively:
- Keep your development workflow in debug mode (
cargo run) while iterating on art, shaders, or data files. - Use a reliable editor that atomically writes files (most IDEs do) to avoid partial writes that could trigger failed reloads.
- Profile the watcher overhead if you target low‑power hardware; consider disabling features via feature flags if needed.
- For custom assets, implement
Asset::reloadto re‑initialize GPU handles.
By following these steps you can cut down iteration time significantly while staying aware of the feature’s constraints.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.