Closed Alekssasho closed 1 year ago
Currently there's no convenience features built in for entity references. I want to improve it eventually: #70.
What you have to do now is match them up yourself. The plugin does provide all the details you need to do so. LDtk entities can be spawned in bevy with the EntityInstance
component, which stores the metadata of that LDtk entity, including its fields. The EntityRef will be the value of one of these fields, and will contain the entity_iid
of the LDtk Entity it's pointing to. From there it's just a matter of figuring out which of the entities spawned by the plugin is associated with that entity_iid
, information also contained in the EntityInstance
component.
There's lots of ways to implement this. Off the top of my head, you could do something like this:
#[derive(Component, Deref, DerefMut)]
struct UnresolvedPointer(String);
impl From<EntityInstance> for UnresolvedPointer {
fn from(value: EntityInstance) -> Self {
if let FieldValue::EntityRef(Some(iid)) = value
.field_instances
.iter()
.find(|f| f.identifier == "MyEntityRefFieldIdentifier".to_string())
.unwrap()
.value
.clone()
{
UnresolvedPointer(iid.entity_iid)
} else {
panic!();
}
}
}
#[derive(Component)]
struct Pointer(Entity);
#[derive(Bundle, LdtkEntity)]
struct PointerBundle {
#[from_entity_instance]
pointer: UnresolvedPointer,
// other components..
}
#[derive(Component, Deref, DerefMut)]
struct EntityIid(String);
impl From<EntityInstance> for EntityIid {
fn from(value: EntityInstance) -> Self {
EntityIid(value.iid)
}
}
#[derive(Bundle, LdtkEntity)]
struct PointedAtBundle {
#[from_entity_instance]
entity_iid: EntityIid,
// other components..
}
fn resolve_pointers_system(
mut commands: Commands,
pointer_query: Query<&UnresolvedPointer>,
pointed_at_query: Query<(Entity, &EntityIid)>,
) {
for pointer in &pointer_query {
if let Some((pointed_at_entity, _)) =
pointed_at_query.iter().find(|(_, id)| id.0 == pointer.0)
{
commands
.entity(pointed_at_entity)
.remove::<UnresolvedPointer>()
.insert(Pointer(pointed_at));
}
}
}
Thanks a lot for the example. I think it would be a good idea to add it as an example file in the repo.
@Trouv The example above only works if the level containing the other entity is loaded.
I've come up with something for when the other level isn't loaded yet, e.g. for a warp destination, but it feels messy.
I'm using the FieldInstanceEntityReference
to find the LayerInstance
and then EntityInstance
in the LdtkAsset
and finally using calculate_transform_from_entity_instance
to get the Transform
. Is there a better way of doing this?
Is there a better way of doing this?
Not currently no, if it's not spawned then doing it through the asset is your only option. I have been considering lately creating a resource that maps ldtk entity iids to their indices in the asset (level index, layer index, then entity index) so users can easily get level and layer data for a given entity, and that would help in your use case too.
How is the supposed way to get an Entity Bevy id from EntityRef loaded from LDtk file ? I have linked EntityInstances and I am not sure how to link them after loading into the ecs of bevy ?