Isometric tiled 2D game performance #8523
-
Hey everyone! I'm currently working on a 2D isometric game that consists of chunks containing tiles. I'm aware that there is bevy_ecs_tilemap and I even tried that out but once I show also around 24k entites, the FPS is only marginally better (24 instead of 16 FPS) than using my implementation. I currently have chunks as an entity and all tiles of that chunk with its relative offset as a child: fn create_chunk_entity<const CHUNK_SIZE: usize>(
commands: &mut Commands,
assets: &AssetCollection,
chunk: &BoardChunk<CHUNK_SIZE>,
) -> Entity {
let mut rng = rand::thread_rng();
let chunk_size = CHUNK_SIZE as TilePos;
let x_chunk = (chunk.index.x * chunk_size) as f32;
let y_chunk = (chunk.index.y * chunk_size) as f32;
let mut chunk_entity = commands.spawn(ChunkBundle {
transform: Transform::from_translation(isometric_to_camera(Vec2::new(x_chunk, y_chunk))),
..default()
});
chunk_entity.with_children(|parent| {
for (y_index, row) in chunk.tile_data.iter().enumerate() {
let y = y_index as WorldPos;
for (x_index, tile) in row.iter().enumerate() {
let x = x_index as WorldPos;
let Some(asset) = &assets.tile_bases[tile.base] else {
continue;
};
parent.spawn(SpriteSheetBundle {
texture_atlas: asset.texture_atlas_handle.clone(),
sprite: TextureAtlasSprite {
index: rng.gen_range(0..asset.n_assets),
custom_size: Some(asset.size),
anchor: asset.anchor.clone(),
..default()
},
transform: Transform::from_translation(isometric_to_camera(Vec2::new(x, y))),
..default()
});
}
}
});
chunk_entity.id()
} Every tile has a texture atlas with multiple variants to choose from, they are chosen randomly. That way I have some variety in sprites being used. I just think "there must be a better way to do it" as after all this is just an array of enum values, and I keep applying the (almost) same textures just to different (static) locations all the time. Do you have any idea how to make the performance better? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
I'm also considering to change the way I render the map from a certain zoom-level altogether and instead of using entities just draw "individual pixels" per tile when you zoom out a lot. |
Beta Was this translation helpful? Give feedback.
-
Are you sure this is a GPU perf issue? Before trying to optimize the rendering aspect, I would first want make sure I know exactly where the slowdown is coming from. Check out the profiling guide. 24K sounds not exactly a lot, but I can see bevy having difficulties if the game isn't built in release mode. Do you run your game with the following?
Debug builds can be 100 times slower than release builds, so make sure to use them when pocking at performance. Furthermore, typically when people say "use chunk entities" they mean that you should use chunks as entity instead of tiles, not both at the same time. This is a recommendation I often see when making voxel games (since the # of entities is a power of 3 instead of 2). But as mentioned earlier, this shouldn't be an issue for 24K entities. I'm personally not well versed enough in tile-based game dev to answer in more details with regard to your setup, so I only gave you some general tips. |
Beta Was this translation helpful? Give feedback.
-
Hey nicopap, thanks for your reply! Ok, now I feel stupid :D This runs with 120 FPS with I followed the docs regarding performance to add this to Cargo.toml: # Enable a small amount of optimization in debug mode
[profile.dev]
opt-level = 1
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
[profile.dev.package."*"]
opt-level = 3 But it seems that was not enough. Regarding your thoughts of chunks as entities: A problem I see with using chunks as entities is also "what exactly do I send to the GPU for that chunk?". Then I would probably have to pre-render the entire chunk somewhere and upload the texture of the entire chunk somewhere. To be honest, the main reason I'm using chunks is because that way I have smaller map parts that take a constant amount of memory and I can lazily generate them, load them from disk or transmit/update them over the network for multiplayer. |
Beta Was this translation helpful? Give feedback.
-
Shameless plug: If you can live without your tiles/chunks being entities but rather living in a managed array, take a look at https://github.com/Droggelbecher/bevy-fast-tilemap |
Beta Was this translation helpful? Give feedback.
Are you sure this is a GPU perf issue? Before trying to optimize the rendering aspect, I would first want make sure I know exactly where the slowdown is coming from. Check out the profiling guide.
24K sounds not exactly a lot, but I can see bevy having difficulties if the game isn't built in release mode. Do you run your game with the following?
Debug builds can be 100 times slower than release builds, so make sure to use them when pocking at performance.
Furthermore, typically when people say "use chunk entities" they mean that you should use chunks as entity instead of tiles, not both at the same time. This is a recommendation I often see when making voxel games (si…