this post was submitted on 16 Jun 2023
7 points (100.0% liked)

GameDev

2764 readers
1 users here now

A community about game development.

Rules:

More rules might follow if they become necessary; general rule is don't be a pain in the butt. Have fun! ♥

GameDev Telegram chat.

founded 1 year ago
MODERATORS
 

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!

top 4 comments
sorted by: hot top controversial new old
[–] your_name_please@lemmy.blahaj.zone 3 points 1 year ago (1 children)

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.

[–] cityboundforest@beehaw.org 1 points 1 year 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@lemmy.ml 1 points 1 year ago (1 children)

You should probably ask over here as well: https://github.com/FraserLee/bevy_sprite3d/issues I havent used this library before but I might take a look once Im out of the bath

[–] babydriver@lemmy.ml 1 points 1 year 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 :(