Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Level spawns twice when LdtkWorldBundle spawns after LevelSelection is inserted #91

Closed
grace125 opened this issue May 27, 2022 · 4 comments · Fixed by #106
Closed

Level spawns twice when LdtkWorldBundle spawns after LevelSelection is inserted #91

grace125 opened this issue May 27, 2022 · 4 comments · Fixed by #106
Labels
bug Something isn't working
Milestone

Comments

@grace125
Copy link

The currently selected level spawns twice if LevelSelection already exists as a resource, and LdtkWorldBundle is spawned after startup. See the following example (given some game.ldtk):

use bevy::prelude::*;
use bevy_ecs_ldtk::prelude::*;

fn main() {
    App::new()
        .add_state(AppState::Loading)
        .add_plugins(DefaultPlugins)
        .add_plugin(LdtkPlugin)
        .insert_resource(LevelSelection::Index(0))
        .add_system(listener)
        .add_system_set(SystemSet::on_enter(AppState::Loading).with_system(spawn_world_bundle))
        .run()
}

#[derive(Clone, Eq, PartialEq, Debug, Hash)]
enum AppState {
    Loading,
}

fn spawn_world_bundle(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn_bundle(LdtkWorldBundle {
        ldtk_handle: asset_server.load("game.ldtk"),
        ..default()
    });
}

fn listener(mut level_events: EventReader<LevelEvent>) {
    level_events.iter().for_each(|l| println!("{:?}", l));
}

The same thing happens when LevelSelection is instead inserted in the spawn_world_bundle system.

However, this does not happen when LevelSelection is first inserted later on, i.e. with a system such as:

fn insert_level_selection(input: Res<Input<KeyCode>>, mut commands: Commands) {
    if input.just_pressed(KeyCode::Space) {
        commands.insert_resource(LevelSelection::Index(0));
    }
}
@Trouv
Copy link
Owner

Trouv commented Jun 16, 2022

Thanks for the report, I'm able to reproduce the issue.
Very strange. I'll look into this before the next release for sure.

@Trouv Trouv added the bug Something isn't working label Jun 16, 2022
@Trouv Trouv added this to the 0.4.0 milestone Jul 17, 2022
@beardedmullett
Copy link

This issue was causing me some problem with my collision detection code. The duplicate entities was messing with my collision resolution, so I did some digging.

In fn process_ldtk_world a new LdtkAsset is processed twice due to new_ldtks: Query<&Handle<LdtkAsset>, Added<Handle<LdtkAsset>>> query and AssetEvent::Created event. Removing the query and it's related code resolves the issue.

It's worth noting that it should have despawned the entities from the first pass but failed to do so because the children didn't exist on the asset.

@Trouv
Copy link
Owner

Trouv commented Jul 27, 2022

I see, thanks for looking into this. I think that change might introduce a regression where new LdtkWorldBundle entities with old Handle<LdtkAsset>s don't get levels spawned. I don't think spawning LdtkWorldBundles in an update after loading the LdtkAsset is a common use case, but I wouldn't want to break it.

Maybe it would be better to just ensure that there are no duplicates in the changed_ldtks: Vec<Handle<LdtkAsset>> in that system. We could use a HashSet over a Vec to enforce the no-duplicates.

Would that resolve your issue as well @beardedmullett ?

@beardedmullett
Copy link

The query and the event seem to occur a frame apart, certainly separate calls to process_ldtk_world, so wouldn't appear in changed_ldtks: Vec<Handle<LdtkAsset>> as a duplicates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants