使用bevy_asset_loader加载.glb资产失败问题排查(Bevy v0.15.1)
Bevy中使用bevy_asset_loader加载GLB场景失败,直接用AssetServer则正常
环境与问题
使用Bevy v0.15.1、bevy_asset_loader v0.22.0并启用3D特性开发应用时,尝试通过AssetCollection将.glb文件加载为Handle<Scene>,代码可编译但模型不显示,且出现「找不到匹配的资产加载器」错误;但直接使用AssetServer加载则正常。
简化代码
#[derive(Clone, Eq, PartialEq, Debug, Hash, Default, States)] pub enum GameState { #[default] Loading, Game } #[derive(AssetCollection, Resource)] pub struct ShipAssets { #[asset(path = "3d/ships/boat-sail-a.glb")] sail_a: Handle<Scene>, #[asset(path = "3d/ships/boat-sail-a.glb")] sail_b: Handle<Scene>, } fn main() { App::new() .add_plugins(DefaultPlugins) .init_state::<GameState>() .add_loading_state( LoadingState::new(GameState::Loading) .continue_to_state(GameState::Game) .load_collection::<ShipAssets>() .load_collection::<MapAssets>() ) .add_systems(Startup, spawn_ship.run_if(in_state(GameState::Game))) .run(); } fn spawn_ship(mut commands: Commands, ship_assets: Res<ShipAssets>) { commands.spawn( ( SceneRoot(ship_assets.sail_a.clone()), Transform::from_xyz(0.0, 0.0, 0.0), ) ); }
错误信息
2025-01-25T00:22:53.704629Z ERROR bevy_asset::server: Could not find an asset loader matching: Loader Name: None; Asset Type: None; Extension: None; Path: Some("3d/ships/boat-sail-a.glb"); 2025-01-25T00:22:53.704629Z ERROR bevy_asset::server: Could not find an asset loader matching: Loader Name: None; Asset Type: None; Extension: None; Path: Some("3d/ships/boat-sail-b.glb");
直接使用AssetServer的可行写法
通过GltfAssetLabel::Scene(0).from_asset("3d/ships/boat-sail-a.glb")指定加载GLB文件中的第一个场景,代码片段:
asset_server.load(GltfAssetLabel::Scene(0).from_asset("3d/ships/boat-sail-a.glb"))
原因与解决方法
问题根源
GLB文件的默认资产加载器是将其解析为Gltf类型,而非直接的Scene类型。直接使用AssetServer时,你通过GltfAssetLabel明确告知要从Gltf资源中提取场景;但AssetCollection默认只会按指定的Handle类型去匹配加载器,找不到能直接将GLB转为Scene的加载器,因此报错。
解决方法1:加载为Gltf后提取场景
修改AssetCollection中的资源类型为Handle<Gltf>,在生成实体时从Gltf中取出对应场景:
#[derive(AssetCollection, Resource)] pub struct ShipAssets { #[asset(path = "3d/ships/boat-sail-a.glb")] sail_a: Handle<Gltf>, #[asset(path = "3d/ships/boat-sail-a.glb")] sail_b: Handle<Gltf>, } fn spawn_ship(mut commands: Commands, ship_assets: Res<ShipAssets>, gltf_assets: Res<Assets<Gltf>>) { if let Some(gltf) = gltf_assets.get(&ship_assets.sail_a) { commands.spawn(( SceneRoot(gltf.scenes[0].clone()), Transform::from_xyz(0.0, 0.0, 0.0), )); } // 同理处理sail_b }
解决方法2:使用bevy_asset_loader的GLB场景加载属性
bevy_asset_loader v0.22.0支持gltf_scene属性,可直接在AssetCollection中指定加载GLB文件中的对应场景,无需手动提取:
#[derive(AssetCollection, Resource)] pub struct ShipAssets { #[asset(path = "3d/ships/boat-sail-a.glb", gltf_scene = 0)] sail_a: Handle<Scene>, #[asset(path = "3d/ships/boat-sail-a.glb", gltf_scene = 0)] sail_b: Handle<Scene>, }
此方法更简洁,能直接得到Handle<Scene>,符合你原本的代码逻辑。
内容的提问来源于stack exchange,提问作者JaB
相关产品推荐
相关产品推荐

