Anatomy of the World
Once an LdtkWorldBundle
is spawned, levels are selected, and the associated assets finish loading, the level spawning process begins.
The result is a deeply nested hierarchy of entities which can be difficult to navigate, but predictable.
It can be useful to write code that makes assumptions about the relationships between bevy_ecs_ldtk
entities.
To assist with this, this chapter will explain the anatomy of a bevy_ecs_ldtk
world.
Hierarchy
The basic hierarchy of spawned entities and their identifying components/bundles are as follows. This does exclude some special cases which are explained in more detail below. Each bullet indent indicates a parent/child relationship.
- The world entity, with an
LdtkWorldBundle
bundle.- The level entities, with a
LevelIid
component.- For Entity layers - a layer entity with just a
LayerMetadata
component.- LDtk Entity entities, with an
EntityInstance
component, or possibly others if you're usingLdtkEntity
registration.
- LDtk Entity entities, with an
- For Tile/AutoTile/IntGrid layers:
bevy_ecs_tilemap
tilemap entities, with aTilemapBundle
and aLayerMetadata
component.- For IntGrid layers - tile entities with an
IntGridCell
component, or possibly others if you're usingLdtkIntCell
registration. - For Tile/AutoTile layers (or IntGrid layers with AutoTile functionality) -
bevy_ecs_tilemap
tile entities, with aTileBundle
bundle.
- For IntGrid layers - tile entities with an
- For Entity layers - a layer entity with just a
- The level entities, with a
Worldly Entities
The LdtkEntity
derive macro allows you to define entities as "worldly".
The intention of this feature is to support entities that are allowed to persist and traverse between levels, like a player in a GridVania layout.
One consequence of an entity being worldly is a change in its placement in the above hierarchy. Instead of being spawned as a child of the Entity layer entity, worldly entities will be children of the world entity (after one update). This makes the worldly entity independent of their origin level, so that if the origin level is unloaded, the worldly entity can still persist.
Furthermore, a worldly entity will not be spawned if it already exists. This prevents two of the same worldly entity existing if the origin level is despawned and respawned. For example, if the worldly player entity traverses far enough away that their origin level is unloaded, then returns to it, there won't suddenly be two players.
Tile metadata components
LDtk allows you to associate metadata with particular tiles in a tileset.
bevy_ecs_ldtk
responds to this by adding additional components to tiles that have metadata in addition to those described in the hierarchy:
Naturally, this can only occur in Tile/AutoTile layers (or IntGrid layers with AutoTile functionality), since the metadata is defined on tilesets.
Level backgrounds
LDtk allows you to supply a background color and a background image for individual levels.
bevy_ecs_ldtk
renders these by default.
The background color is spawned as a normal bevy SpriteBundle
, as a child of the level entity.
The background image, if it exists, is also spawned as a SpriteBundle
.
These background sprites can be disabled (not spawned) using the settings resource LdtkSettings
:
use bevy::prelude::*; use bevy_ecs_ldtk::prelude::*; fn main() { App::new() // other App builders .insert_resource(LdtkSettings { level_background: LevelBackground::Nonexistent, ..default() }) .run(); }
Layers with colliding tiles
It is possible for LDtk Tile/AutoTile layers to have colliding tiles. In other words, a single layer can have more than one tile in the same location.
bevy_ecs_tilemap
tilemaps only allow one tile per position.
So, bevy_ecs_ldtk
supports layers with colliding tiles by spawning multiple tilemaps.
Each of them will have the same LayerMetadata
component.
This means that users cannot assume that there will be only one LayerMetadata
entity per layer.
Z order
To correctly define the render order of the tiles and entities in a level, bevy_ecs_ldtk
uses the z
value of their Transform
components.
Z order is only applied to level backgrounds, layer entities, and worldly entities.
Tiles and non-worldly entities will simply inherit the z-ordering in their GlobalTransform
.
bevy_ecs_ldtk
begins with a z
value of 0 for the background-most entities, and increments this by 1 for each layer above that.
This sounds simple, but can actually be pretty difficult to predict thanks to some special cases mentioned above.
Background colors and background images will usually get the z
values of 0 and 1 respectively.
However, if the background image does not exist, the z
value of 1 will be freed for the next layer instead.
If level backgrounds are disabled entirely, both 0 and 1 will be freed for the next layer.
From here, each layer generally increments the z
value by 1.
However, note that there can be multiple layer entities for a single LDtk layer.
Each of these additional layer entities will also increment the z
value by 1.
Since this can be difficult to predict, it is generally recommended to avoid making assumptions about the z
value of a layer.