So I’m currently working with Bevy to make a game with a style similar to that of Octopath Traveler. I’m using the bevy_sprite3d crate to render sprites in the 3D space. I’m currently working on writing the code for the battle scene of my JRPG. However, whenever I try to load multiple sprites into the scene, it gives me the following error:

error[B0002]: ResMut<bevy_asset::assets::Assets<bevy_sprite::texture_atlas::TextureAtlas>> in system load_sprites conflicts with a previous ResMut<bevy_asset::assets::Assets<bevy_sprite::texture_atlas::TextureAtlas>> access. Consider removing the duplicate access.

relevant system code
fn load_sprites(mut commands: Commands, asset_server: Res<AssetServer>, sprites_in_scene: Res<SpritesInScene>, mut texture_atlases: ResMut<Assets<TextureAtlas>>, mut sprite_params: Sprite3dParams) {
    // Load first player sprite
    commands.spawn(AtlasSprite3d {
        atlas: texture_atlases.add(get_texture_atlas(&asset_server, sprites_in_scene.player_sprite1 /* u32 */, (37, 38), 19)),

        pixels_per_metre: 32.,
        partial_alpha: true,
        unlit: true,

        ..default()
    }.bundle(&mut sprite_params))
    .insert(AnimationTimer(Timer::from_seconds(3. / 60., TimerMode::Repeating)))
    .insert(Transform::from_xyz(-5., 0., 0.));

    // Load second player sprite if it exists
    if let Some(id) = sprites_in_scene.player_sprite2 {
        commands.spawn(AtlasSprite3d {
            atlas: texture_atlases.add(get_texture_atlas(&asset_server, id, (1, 1), 1)),

            pixels_per_metre: 32.,
            partial_alpha: true,
            unlit: true,

            ..default()
        }.bundle(&mut sprite_params))
        .insert(AnimationTimer(Timer::from_seconds(3. / 60., TimerMode::Repeating)))
        .insert(Transform::from_xyz(-2.5, 0., 0.));
    }

    // Load first enemy sprite
    commands.spawn(AtlasSprite3d {
        atlas: texture_atlases.add(get_texture_atlas(&asset_server, sprites_in_scene.enemy_sprite1 /* u32 */, (42, 42), 21)),

        pixels_per_metre: 32.,
        partial_alpha: true,
        unlit: true,

        ..default()
    }.bundle(&mut sprite_params))
    .insert(AnimationTimer(Timer::from_seconds(3. / 60., TimerMode::Repeating)))
    .insert(Transform::from_xyz(5., 0., 0.));

    // Load second enemy sprite if it exists
    if let Some(id) = sprites_in_scene.enemy_sprite2 {
        commands.spawn(AtlasSprite3d {
            atlas: texture_atlases.add(get_texture_atlas(&asset_server, id, (1, 1), 1)),

            pixels_per_metre: 32.,
            partial_alpha: true,
            unlit: true,

            ..default()
        }.bundle(&mut sprite_params))
        .insert(AnimationTimer(Timer::from_seconds(3. / 60., TimerMode::Repeating)))
        .insert(Transform::from_xyz(2.5, 0., 0.));
    }
}

// The signature for get_texture_atlas:
fn get_texture_atlas(asset_server: &Res<AssetServer>, id: u32, tile_size: (u32, u32), row_num: usize) -> TextureAtlas

Am I doing this wrong? Is there a better way to load multiple texture atlases for the different entities in my battle scene? Thanks in advance!

    • babydriver
      link
      fedilink
      English
      arrow-up
      1
      ·
      2 years ago

      ok so I’m out of the bath.

      #[derive(SystemParam)]
      pub struct Sprite3dParams<'w, 's> {
          pub meshes    : ResMut<'w, Assets<Mesh>>,
          pub materials : ResMut<'w, Assets<StandardMaterial>>,
          pub images    : ResMut<'w, Assets<Image>>,
          pub atlases   : ResMut<'w, Assets<TextureAtlas>>,
          pub sr        : ResMut<'w, Sprite3dRes>,
          #[system_param(ignore)]
          marker: PhantomData<&'s usize>,
      }
      

      It seems like Sprite3dParams is already accessing Assets<TextureAtlas> which is why you get the the error. So you need to either remove texture_atlases or sprite_params. in your system.

      have you looked at this example? I won’t be much help sorry :(

      • Cass.Forest@beehaw.orgOP
        link
        fedilink
        English
        arrow-up
        2
        ·
        2 years ago

        I have and I now understand why in that example, they split up asset loading and bundle spawning into two different systems. Note to self: it helps to check the source code of the stuff you use when it’s available!