mcpField
B
bevy-custom-assets

bevy-custom-assets

github.com/chrisgliddon开发2683 次安装9 周前更新
代码仓库

关于 bevy-custom-assets

面向使用 Bevy 0.19 的开发者,说明自定义资源加载器的实现方式及版本变更注意事项,涵盖异步读取和依赖资源加载。

主要功能

  1. 01实现自定义资源加载器
  2. 02异步读取与随机访问
  3. 03通过 LoadContext 加载依赖
  4. 04适配 Bevy 0.19 API 变更

适用场景

  1. 01加载自定义二进制或文本格式
  2. 02构建依赖纹理等资源的关卡加载器
  3. 03迁移旧版嵌套加载代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/chrisgliddon/bevy-skills --skill bevy-custom-assets

安装后在 Claude Code 中输入/bevy-custom-assets确认已加载。

详细介绍

Bevy 0.19 — 自定义资源加载器

何时使用此技能

  • 加载自定义二进制或文本格式(专有游戏数据、配套配置等)。
  • 生成依赖其他资源的资源(例如,会加载引用纹理的关卡加载器)。
  • 将 LoadContext::loader() 或旧版 NestedLoader 迁移到 load_builder() / NestedLoadBuilder。
  • 需要异步访问底层文件(reader.read_to_end、reader.seekable())。
  • 编译器错误:“MyLoader: TypePath is not implemented”——0.18 要求加载器必须实现 TypePath。

标准模式

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);
    }
}

请求 Reader 提供随机访问能力

// 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 注意事项

  • 加载器结构体必须使用 #[derive(TypePath)](不能只在资源上使用)。0.18 强制要求这一点,以便反射加载器。否则会出现:“MyLoader: TypePath is not implemented”。
  • LoadContext::path() 返回 AssetPath,而不是 &Path。若要获取平台路径,请对其调用 .path():ctx.path().path()。
  • LoadContext::asset_bytes() 已移除。 在 load 异步函数中使用 let mut bytes = Vec::new(); reader.read_to_end(&mut bytes).await?;,或使用 reader.seekable() 实现随机访问。
  • 必须通过 LoadContext 加载依赖项。在加载器中调用 asset_server.load(...) 不会将结果注册为正在构建的资源的依赖项——请使用 load_context.load_builder().load(...)(或便捷方法 load(...)),以便正确触发 AssetEvent::LoadedWithDependencies。
  • LoadContext::loader() 已在 0.19 中替换。 请使用 load_context.load_builder()。即时加载改为 load_value,动态加载改为 load_erased,未知类型加载则改为 builder 操作 load_untyped。
  • 自定义 Reader 实现必须在 0.19 中定义 seekable()。 仅当该类型实现了 AsyncSeek 时才返回 Ok(self);否则返回 Err(ReaderNotSeekableError)。
  • AssetLoader 是异步的,但不能在其中调用 tokio::spawn——Bevy 使用自己的执行器,而不是 Tokio。对于计算密集型工作,请使用 bevy::tasks::futures_lite 或 bevy::tasks::AsyncComputeTaskPool。
  • 资源类型必须使用 #[derive(Asset)],并结合 TypePath。 资源的 Settings 类型必须满足 Default + Serialize + DeserializeOwned + Send + Sync + 'static,才能参与 .meta 文件处理。
  • 扩展名会按完整后缀匹配。 "level.ron" 会匹配 foo.level.ron,但不会匹配 foo.ron——这有助于与通用 RON 格式区分。

另请参阅

  • bevy-assets — 加载完成后使用 Handle<MyAsset>。
  • bevy-voxel-data — 由 RON 驱动的资源模式。
  • bevy-migration-0-17-to-0-18 — 移除 LoadContext::asset_bytes。
  • bevy-migration-0-18-to-0-19 — 嵌套加载 builder 与 Reader 变更。

评论

支持 Markdown