Skip to content

Commit

Permalink
fix: Un-register component keys down the component tree (#2792)
Browse files Browse the repository at this point in the history
ComponentKey for children components were not getting unregistered when
the sub-tree was removed from the game. As a result:

- same key couldn't be reused
- components with such keys couldn't be readded once removed
- component with such keys were not being garbage collected (didn't
actually verify this one though)
  • Loading branch information
ufrshubham authored Oct 4, 2023
1 parent ab329f7 commit 0f679b3
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
16 changes: 10 additions & 6 deletions packages/flame/lib/src/components/core/component.dart
Original file line number Diff line number Diff line change
Expand Up @@ -896,17 +896,12 @@ class Component {
void _remove() {
assert(_parent != null, 'Trying to remove a component with no parent');

if (_key != null) {
final game = findGame();
if (game is FlameGame) {
game.unregisterKey(_key!);
}
}
_parent!.children.remove(this);
propagateToChildren(
(Component component) {
component
..onRemove()
.._unregisterKey()
.._clearMountedBit()
.._clearRemovingBit()
.._setRemovedBit()
Expand All @@ -920,6 +915,15 @@ class Component {
);
}

void _unregisterKey() {
if (_key != null) {
final game = findGame();
if (game is FlameGame) {
game.unregisterKey(_key!);
}
}
}

//#endregion

//#region Debugging assistance
Expand Down
23 changes: 23 additions & 0 deletions packages/flame/test/components/component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,29 @@ void main() {
},
);

testWithFlameGame(
'Removed keys can be reused by components',
(game) async {
final key = ComponentKey.named('A');
final parent1 = Component(children: [ComponentA(key: key)]);

game.world.add(parent1);
await game.ready();

parent1.removeFromParent();
await game.ready();

final component = ComponentA(key: key);
final parent2 = Component(children: [component]);

game.world.add(parent2);
await game.ready();

final retrieved1 = game.findByKey(key);
expect(retrieved1, equals(component));
},
);

testWithFlameGame(
'Throws assertion error when registering a component with the same key',
(game) async {
Expand Down

0 comments on commit 0f679b3

Please sign in to comment.