bevy_tilemap icon indicating copy to clipboard operation
bevy_tilemap copied to clipboard

Event is not automatically added

Open thorlucas opened this issue 3 years ago • 4 comments

Bevy Tilemap version

0.4.0

What you did

In Bevy 0.5, the following pattern should work:

pub fn chunk_event_handler(mut reader: EventReader<TilemapChunkEvent>) {
    for event in reader.iter() {
        match event {
            TilemapChunkEvent::Spawned { point } => {
                println!("Spawned point: {:?}", point);
            },
            _ => (),
        }
    }
}

However, we get:

Requested resource does not exist: bevy_app::event::Events<bevy_tilemap::event::TilemapChunkEvent>

Perhaps the TilemapPlugin does not call app.add_event::<TilemapChunkEvent>()?

thorlucas avatar Apr 08 '21 07:04 thorlucas

The events are inclusive of the Tilemap itself, and not outside. This was actually done intentionally. I tried to do it otherwise, but I had ran into issues where you have to actually push it in as an argument, making it a bit awkward to use. The Tilemap is meant to act like it's own standalone asset server though. This was done through discussions with some, including some insight from cart who generally agreed with my approach.

You can get the events from Tilemap::chunk_events() however. Though, that should be renamed to just events at some point...

If you have an alternative solution where Tilemap can hold TilemapChunkEvent alongside the asset server, that would be awesome. I couldn't think of anything at the time though.

joshuajbouw avatar Apr 08 '21 09:04 joshuajbouw

@joshuajbouw I'm not familiar enough with the Bevy internals to be of any help here.

But I am unsure then how to use chunk_events(). Here's what I'm doing right now:

In my setup function, I:

  • Create the tilemap
  • Call tilemap.spawn_chunk((0, 0)).unwrap();
  • Add tilemap as a resource

Then I have the system:

pub fn chunk_event_handler(query: Query<&Tilemap>) {
    if let Ok(map) = query.single() {
        let events = map.chunk_events();
        let mut reader = events.get_reader();
        for event in reader.iter(events) {
            match event {
                TilemapChunkEvent::Spawned { point } => {
                    println!("Spawned {:?}", point);
                }
                _ => (),
            }
        }
    }
}

The intention is that the println line would either load the chunks from disk if they already exist, or instead issue another event requesting world gen to create new data there.

But here's the output we get:

Spawned Point2 { x: 0, y: 0 }
Apr 11 19:00:42.917  WARN bevy_tilemap::system: Can not get chunk at (0, 0), possible bug report me
Spawned Point2 { x: 0, y: 0 }

~~Why is the event being issued twice?~~ And why does bevy_tilemap complain that it cannot get the chunk, if we have .auto_chunk() enabled?

Edit: It seems that using my own Local<ManualEventReader<T>> fixes the double event issue.

thorlucas avatar Apr 12 '21 02:04 thorlucas

Note that if I manually insert_chunk() then it does not issue that warning, but we still get the issue with the event being issued twice.

This is particularly an issue with .auto_spawn() because the .auto_chunk() does not seem to properly generate chunks that auto spawn requests.

thorlucas avatar Apr 12 '21 02:04 thorlucas

Note that this also causes a race condition; if my generate_chunk_event_handler() runs before some of bevy_tilemaps systems, then tiles are inserted properly and auto chunk does its thing:

Spawned Point2 { x: 0, y: 0 }
Got generate chunk event: Point2 { x: 0, y: 0 }
Apr 11 19:18:56.266  INFO bevy_tilemap::system: Chunk (0, 0) spawned

However, if my generate chunk event handler happens after, we get the same issue as before. Auto chunk does not create the chunk requested by auto spawn, and we get this:

Spawned Point2 { x: 0, y: 0 }
Apr 11 19:20:52.619  WARN bevy_tilemap::system: Can not get chunk at (0, 0), possible bug report me
Got generate chunk event: Point2 { x: 0, y: 0 }

And nothing is drawn to the screen.

thorlucas avatar Apr 12 '21 02:04 thorlucas