Indra-db / Flecs-Rust

Rust API for Flecs: A Fast and Flexible Entity Component System (ECS)
MIT License
194 stars 11 forks source link

Optional tags are not included in query results #209

Closed Shelim closed 6 days ago

Shelim commented 1 week ago

Thank you guys for your awesome work and so far this tool is amazing - but I happen to break stuff a little more :)

MRE Code

use flecs_ecs::prelude::*;

#[derive(Component)]
pub struct ExampleComponent;

#[derive(Component)]
pub struct ExampleOptionalComponent;

fn main() {
    let world = World::new();

    let entity1 = world.entity_named("Example1").add::<ExampleComponent>();
    let entity2 = world.entity_named("Example2").add::<ExampleComponent>().add::<ExampleOptionalComponent>();

    let query = world.query::<(&ExampleComponent, Option<&ExampleOptionalComponent>)>().build();

    query.each_entity(|entity, (example_component, example_option_component)| {
        println!("I am component {} with optional: {}", entity.name(), example_option_component.is_some())
    });
}

Expected result

Second entity should have is_some returning true

Actual result

I am component Example1 with optional: false
I am component Example2 with optional: false

Additional info

Crate version: 0.1.3 Platform: Windows 11 x64

When quering for non-tag (ie struct that actually has some fields), the result is correct (false then true).

Indra-db commented 6 days ago

This issue was fixed on main beforehand, I will be updating to a new release soonTM. Been very busy in real life with traveling with a friend + my birthday.

it now compile time asserts as following:

        const {
            assert!(
                !T::CONTAINS_ANY_TAG_TERM,
                "a type provided in the query signature is a Tag and cannot be used with `.each`. use `.run` instead or provide the tag with `.with()`"
            );
        }
    Thank you so much for the issue!
Shelim commented 6 days ago

Is there any reason each cannot be used by tags? Because it is actually a much more problematic issue, in case we're talking of complex dataset of 1,000,000+ entities

  1. To use run I need to know the order of the components. I actually can't know if the entities were made in different places with add/removal components in place and so on...
  2. To use with I need to query for all entities that could contain tag. In my case that mean iterating 100x the results, in case of rare tags (<1% population)
  3. To use non-empty components as tags (which is actually the solution I would prefer) means inducing memory/cache miss cost for each operation reflecting them