#ECS behaviour with hierarchy

7 messages · Page 1 of 1 (latest)

crude plover
#

I'm trying to understand some ECS behaviour with hierarchy but i'm struggling.
I wrote this test:

    #[derive(Resource, Default)]
    struct Counter(usize);

    fn observe_children_updated(trigger: Trigger<OnAdd, ChildOf>, parent: Query<&ChildOf>, children: Query<&Children>, mut counter: ResMut<Counter>) {
        if let Some(parent) = parent.related(trigger.target()) {
            std::dbg!("ChildOf is present");
            if let Ok(children) = children.get(parent) {
                std::dbg!("Parent's children:", children);
                counter.0 += 1
            }
        }
    }

    #[test]
    fn child_spawn_observer() {
        let mut world = World::new();
        world.init_resource::<Counter>();
        world.add_observer(observe_children_updated);
        let parent = world.spawn_empty().id();
        let child = world.spawn(ChildOf(parent));
        let child_2 = world.spawn(ChildOf(parent));
        assert_eq!(world.resource::<Counter>().0, 1);
    }

What I see is:

"ChildOf is present" = "ChildOf is present"
"ChildOf is present" = "ChildOf is present"
"Parent's children:" = "Parent's children:"
children = Children(
    [
        2v1#4294967298,
    ],
)

It makes sense that Children is only printed on the second call. On the first call, when ChildOf is inserted, the order of operations is:

  • ChildOf inserted
  • on-add hook runs, queues a command to insert Children on parent
  • parent observer runs but Children is missing
  • flush, which adds Children on the parent

But I don't get why when the second child gets inserted; the log doesn't show both children inside of Children, since the order should be:

  • ChildOf inserted
  • on-add hook runs, adds an extra child to the Children component of the parent
  • parent observers runs and queries Children => is it we don't call update_archetypes() so the Query hasn't been updated?
burnt terrace
#

@winter pasture triggers run before the relashionships are consolidated?

#

i suspect the the order of operations here is

Spawn entity with `ChildOf`
Runs trigger for `OnAdd, ChildOf`
Relationship is updated and `Children` is added to the parent

that way, on the first trigger the parent still does not have Children

crude plover
#

No the order is ComponentHook -> Observer, and there is no flush_commands between them.
I guess the absence of flush also means that the second Query isn't updated when it runs

#

this means that using observers with relations is very brittle. @tulip igloo I don't know if you have thoughts on this

tulip igloo
tulip igloo