bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
34.19k stars 3.34k forks source link

First-party tile maps #13782

Open alice-i-cecile opened 1 month ago

alice-i-cecile commented 1 month ago

What problem does this solve or what need does it fill?

Tile maps are a key part of many 2D games, both 2D and 3D.

There is a large amount of complexity here: API design, performance and features are all challenging.

What solution would you like?

Bevy should make its own tilemap crate (one day) using a working group.

Some features:

What alternative(s) have you considered?

We could upstream one of the existing tilemap crates:

  1. bevy_ecs_tilemap: challenging to maintain, complex API, poor performance at high map sizes. Lots of features though.
  2. bevy_tilemap: dead since Bevy 0.5
  3. bevy_entitles: a newer candidate, I'm personally unsure how this compares.

None of these strike me as exceptionally good candidates, but the working group should look closely at this for prior art.

Additional context

This is one of the prime formats for content authoring in the editor. Without a first-party tilemap format, the editor will be much less useful for 2D games.

This is a large initiative, please don't try to tackle this without first forming a working group.

IceSentry commented 1 month ago

I personally think bevy should first have a first party way to render a tilemap. Without any fancy features like LDTK or Tiled integration, once we have a first party tilemap rendering solution it will be way easier for third party to support those integrations.

I'm also not sure if y-sorting should be part of a tilemap renderer. The way I see it, tiles are intended to be behind everything and if you want to add sparse entities with y-sorting that should be done with mesh2d/sprites

alice-i-cecile commented 1 month ago

I'm fully on board with that as an initial solution :) Rendering and a standard performant data structure are the hardest bits IMO.

MScottMcBee commented 1 month ago

In my game, most entities live on a layer in between background and foreground tilemap layers. I don't think tiles need their own sorting, but handling multiple layers with the ability to control layer sorting is important.

s-puig commented 3 weeks ago

I'm also not sure if y-sorting should be part of a tilemap render. The way I see it, tiles are intended to be behind everything and if you want to add spares entities with y-sorting that should be done with mesh2d/sprites

I disagree. Y-sorting is pretty much a requirement for isometric tilesets.

Alternatives

There is also bevy-fast-tilemap.

IceSentry commented 3 weeks ago

I disagree. Y-sorting is pretty much a requirement for isometric tilesets.

It doesn't need to be part of the renderer. All the renderer needs is to take depth into account even in 2d. I already have a PR for that. Once you have depth you can just set it based on the z-index and trivially implement y-sorting user side. The renderer doesn't need to know about y-sorting.

NoahShomette commented 3 weeks ago

Alternatives

Another alternative that is more similar to bevy_tilemap than any other current crate is my crate bevy_sparse_tilemap. It's pretty simple feature wise and a bit clunky to look at but it's pretty simple to use and interact with and has very good baseline performance due to dodging the high entity count issue that the other crates run into.

The main goal for this crate was to not do an entity for every tile. This crate supports both dense and sparse maps and dense is basically a Vec<Vec<TileData>>. It has a built in escape hatch to spawn/map an entity to a given tile so you can keep track of unique data/tiles that aren't default anymore. This keeps entity counts very low which really impacts performance rn. This crate also doesn't currently handle any rendering (I use bevy_fast_tilemap in the projects I have that use this crate).

The crate currently supports multiple tilemap types, very very large maps (15k x 15k in my tests), and I have plans to add more helper related stuff like tile->world, iteration functions, as well as I'd like to fix the generics hell it's in rn from the refactor to support multiple tilemap types.

jamescarterbell commented 1 week ago

Tilemaps are a bit cursed in bevy right now for two reasons:

  1. Deciding whether to represent tiles as entities is a big decision: it seems reasonable on its face but doesn't seem to scale well for a variety of reasons.
  2. Without real secondary indexing support, accessing tiles is a PITA and keeping any secondary index up to date is also a pain.

On top of that, any built in tilemaps would have to deal with chunking or not chunking, infinite vs not infinite, tilemaps themselves as entities, etc...

For what it's worth, I also have a crate that's just dealing with tile accessing APIs, but I have some new ideas to make maintaining the indices much nicer:

https://github.com/jamescarterbell/bevy_tiles

(I'll freely give up the name btw)