— No reviews yet
0 installs
9 views
0.0% view→install
Install
$ agentstack add skill-chrisgliddon-bevy-skills-bevy-custom-assets ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Are you the author of Bevy Custom Assets? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claimAbout
Bevy 0.18 — 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).
- 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 {
// 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 = load_context.load(&level.thumbnail);
Ok(level)
}
fn extensions(&self) -> &[&str] {
&["level.ron"]
}
}
pub struct LevelLoaderPlugin;
impl Plugin for LevelLoaderPlugin {
fn build(&self, app: &mut App) {
app.init_asset::()
.register_asset_loader(LevelLoader);
}
}
Asking the reader for random access
// 0.18: bevy::asset::io::Reader gained `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(())
# }
Gotchas (0.18)
#[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()returnsAssetPath, not&Path. To get the platform path, use.path()on it:ctx.path().path().LoadContext::asset_bytes()is gone. Uselet 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(...)soAssetEvent::LoadedWithDependenciesfires correctly. AssetLoaderisasyncbut you can'ttokio::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 withTypePath. 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 aHandleonce it's loaded.bevy-voxel-data— RON-driven asset patterns.bevy-migration-0-17-to-0-18—LoadContext::asset_bytesremoval.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: chrisgliddon
- Source: chrisgliddon/bevy-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.