Come usare
- Copia il comando e controlla il pacchetto prima di installarlo nel tuo ambiente agente.
- Controlla strumenti, credenziali e ambienti richiesti nel documento originale.
- Descrivi input e risultato desiderato; confronta l’output con le fonti.
npx skills add https://github.com/chrisgliddon/bevy-skills --skill bevy-custom-assetsPrima di iniziare
- L’installazione non include abbonamenti, quote API o accesso ai file.
- Stelle e installazioni indicano attività, non un test indipendente di qualità o sicurezza.
Contenuto dal repository con titoli, esempi, codice, tabelle, link e immagini preservati.
Bevy 0.19 — Custom asset loaders
When to use this skill
- Loading a custom binary or text format (proprietary game data, sidecar configs, etc.).
- Producing an asset that depends on other assets (e.g. a level loader that pulls referenced textures).
- Migrating
LoadContext::loader()or an oldNestedLoadertoload_builder()/NestedLoadBuilder. - Needing async access to the underlying file (
reader.read_to_end,reader.seekable()). - Compiler error: "
MyLoader: TypePathis not implemented" — 0.18 madeTypePathmandatory on loaders.
Canonical pattern
use bevy::asset::io::Reader;
use bevy::asset::{Asset, AssetApp, AssetLoader, LoadContext};
use bevy::prelude::*;
use bevy::reflect::TypePath;
use serde::Deserialize;
use thiserror::Error;
#[derive(Asset, TypePath, Debug, Deserialize)]
pub struct LevelDef {
pub name: String,
pub gravity: f32,
pub thumbnail: String, // path to a referenced texture asset
}
#[derive(TypePath)] // 0.18: required on the loader itself.
pub struct LevelLoader;
#[derive(Debug, Error)]
pub enum LevelLoaderError {
#[error("io: {0}")]
Io(#[from] std::io::Error),
#[error("parse: {0}")]
Parse(#[from] ron::error::SpannedError),
}
impl AssetLoader for LevelLoader {
type Asset = LevelDef;
type Settings = ();
type Error = LevelLoaderError;
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &Self::Settings,
load_context: &mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
// Pull the whole file. For very large files prefer `seekable()`.
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let level: LevelDef = ron::de::from_bytes(&bytes)?;
// Pull in a referenced asset so it loads alongside this one.
// The resulting handle ends up tracked as a dependency.
let _: Handle<Image> = load_context.load_builder().load(level.thumbnail.clone());
Ok(level)
}
fn extensions(&self) -> &[&str] {
&["level.ron"]
}
}
pub struct LevelLoaderPlugin;
impl Plugin for LevelLoaderPlugin {
fn build(&self, app: &mut App) {
app.init_asset::<LevelDef>()
.register_asset_loader(LevelLoader);
}
}Asking the reader for random access
// Bevy 0.19 requires Reader implementations to expose `seekable()`.
# use bevy::asset::io::Reader;
# async fn _example(reader: &mut dyn Reader) -> std::io::Result<()> {
match reader.seekable() {
Ok(seekable) => {
// SeekableReader supports `seek(SeekFrom::Start(n))`, `seek(SeekFrom::End(-n))`, etc.
let _ = seekable;
}
Err(_) => {
// Source isn't seekable (e.g. HTTP backend). Fall back to streaming.
}
}
# Ok(())
# }Bevy 0.19 gotchas
- `#[derive(TypePath)]` is required on the loader struct (not just the asset). 0.18 enforces this so loaders can be reflected. Without it: "
MyLoader: TypePathis not implemented". - `LoadContext::path()` returns `AssetPath`, not
&Path. To get the platform path, use.path()on it:ctx.path().path(). - `LoadContext::asset_bytes()` is gone. Use
let mut bytes = Vec::new(); reader.read_to_end(&mut bytes).await?;inside theloadasync fn, orreader.seekable()for random access. - Dependencies must be loaded through `LoadContext`.
asset_server.load(...)from inside a loader does not register the result as a dependency of the asset being built — useload_context.load_builder().load(...)(or theload(...)convenience method) soAssetEvent::LoadedWithDependenciesfires correctly. - `LoadContext::loader()` was replaced in 0.19. Use
load_context.load_builder(). Immediate loads becameload_value, dynamic loads becameload_erased, and unknown-type loads becameload_untypedbuilder operations. - Custom `Reader` implementations must define `seekable()` in 0.19. Return
Ok(self)only when the type implementsAsyncSeek; otherwise returnErr(ReaderNotSeekableError). - `AssetLoader` is `async` but you can't
tokio::spawninside it — the executor is Bevy's, not Tokio's. Usebevy::tasks::futures_liteorbevy::tasks::AsyncComputeTaskPoolfor compute-heavy work. - `#[derive(Asset)]` is required on the asset type and combined with
TypePath. The asset'sSettingstype must beDefault + Serialize + DeserializeOwned + Send + Sync + 'staticto participate in.metafiles. - Extensions are matched on the full suffix.
"level.ron"matchesfoo.level.ronbut notfoo.ron— useful for disambiguating from generic RON.
See also
bevy-assets— using aHandle<MyAsset>once it's loaded.bevy-voxel-data— RON-driven asset patterns.bevy-migration-0-17-to-0-18—LoadContext::asset_bytesremoval.bevy-migration-0-18-to-0-19— nested load builders and reader changes.




