flame icon indicating copy to clipboard operation
flame copied to clipboard

removeAll(children) crashes in onRemove

Open spydon opened this issue 2 years ago • 2 comments

Current bug behavior

If you do removeAll(children) in a component's onRemove method it will assert with:

threw _AssertionError:<'package:flame/src/components/core/component.dart': Failed assertion: line 627 pos 7: 'child._parent != null': Trying to remove a component that doesn't belong to any parent>

Expected behavior

To be able to remove all children in onRemove so that one can do clean-up in there, if you add the children in onMount for example.

Steps to reproduce

      testWithFlameGame(
        'Remove all children in onRemove',
        (game) async {
          final component = _RemoveAllChildrenComponent();
          component.addAll([Component(), Component()]);
          game.add(component);
          await game.ready();
          expect(() => game.remove(component), returnsNormally);
          expect(() => game.update(0), returnsNormally); // Here is the assertion.
        },
      );


class _RemoveAllChildrenComponent extends Component {
  @override
  void onRemove() {
    removeAll(children);
  }
}

More environment information

  • Flame version: main

spydon avatar Sep 18 '23 10:09 spydon

Hi there !

I've ran some tests, and according to the doc, onRemove is also called on all the children of the component when you call game.remove(component)

If you add a

class _RemoveWatcherComponent extends Component {
  @override
  void onRemove() {
    debugPrint('onRemove');
    super.onRemove();
  }
}

and transform using component.addAll([Component(), Component()]); you can see that calling game.remove(component) calls onRemove on every child of component before calling onRemove() on the component itself.

It might be because of propagateToChildren in Component#_remove that calls onRemove without calling _remove, therefor putting _parent = null without removing itself from the list of children ?

Is it possible that the issue comes from there ?

qk7b avatar Oct 06 '23 08:10 qk7b

It might be because of propagateToChildren in Component#_remove that calls onRemove without calling _remove, therefor putting _parent = null without removing itself from the list of children ?

Is it possible that the issue comes from there ?

Yeah, that's definitely where it comes from. Not sure how to solve it nicely though, because we want the children to have their onRemove called removed before the parent is removed.

spydon avatar Oct 09 '23 12:10 spydon