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!

  • your_name_please@lemmy.blahaj.zone
    link
    fedilink
    English
    arrow-up
    3
    ·
    2 years ago

    Logic Projects on YouTube has a RPG they’re working on that could be relevant to you.

    I’ve tried something myself and ended up writing my own data structures to hold handles to the sprites and change them as necessary. But that’s a lot of work still and not sure if it’s the best long-term.

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

      Hello! So I ended up fixing this issue with sprite loading and figured out how to load multiple sprites in the scene. It turns out that I can’t load the images and then spawn in the sprite objs in the same function because of Rust rules 🤷

      Anyhow, I am having a different issue now, and I’ve made a new post about it here.

    • 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!