Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

removeAll(children) crashes in onRemove #2743

Open
spydon opened this issue Sep 18, 2023 · 2 comments
Open

removeAll(children) crashes in onRemove #2743

spydon opened this issue Sep 18, 2023 · 2 comments
Labels

Comments

@spydon
Copy link
Member

spydon commented Sep 18, 2023

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 spydon added the bug label Sep 18, 2023
@quentin7b
Copy link
Contributor

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 ?

@spydon
Copy link
Member Author

spydon commented Oct 9, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants