Skip to content
samme edited this page Nov 4, 2024 · 12 revisions

Groups are logical containers for game objects. They're not displayable (that would be a Container).

Groups are used for

  • Keeping a set of game objects
  • Batch creating game objects
  • Pooling (recycling) game objects
  • Calling a game object's update() method automatically

Creating groups

const group = this.add.group();

If you give a config argument it's interpreted as both GroupConfig and GroupCreateConfig, meaning it will create some members if key (texture) is included (see Batch creation). active is ambiguous.

Groups as sets

This has some advantages over managing your own array of game objects:

  • Duplicate game objects are never added
  • You can add and remove game objects without doing any splicing
  • If you destroy a game object it's automatically removed from any groups it belongs to

Game objects can belong to more than one group.

Group size

The group size is group.getLength() or group.children.size.

Iterate a group

getChildren() and children.entries are identical.

for (const member of group.getChildren()) {/* … */}

group.getChildren().forEach((member) => {/* … */});

// With `iterate()` you must not add or remove group members during the loop
group.children.iterate((member) => {/* … */});

// With `each()` you may add or remove group members during the loop
group.children.each((member) => {/* … */});

Update group members

Use runChildUpdate to call group members' update() methods automatically. It will happen via the scene PRE_UPDATE event, before scene update(). Only active members are updated.

Updatable game objects should be in only one updating group, so they don't get updated twice per step.

const sprite = this.add.sprite(/*…*/);

sprite.update = function (time, delta) {
  /*…*/
};

const group = this.add.group({ runChildUpdate: true });

group.add(sprite);

You can toggle updates on or off:

group.runChildUpdate = false;

An inactive group doesn't update its children.

Groups in colliders

You can pass a group directly to a physics collider.

this.physics.add.overlap(group);

Batch creation

If you use classType it must have the constructor arguments (scene, x, y, texture, frame), like Image or Sprite.

With createMultiple() you must pass at least key (texture). The group's defaultKey isn't used.

const group = this.add.group({
  classType: FancySprite,
});

group.createMultiple({
  key: 'block',
  quantity: 12,
  createCallback: (member) => {
    /*…*/
  },
});

You can use create() for your own batches.

const group = this.add.group({
  classType: FancySprite,
  defaultKey: 'block',
  defaultFrame: 1,
});

group.create(0, 0);
group.create(0, 16);
group.create(0, 32);

If your group members don't have a constructor like (scene, x, y, texture, frame), then don't use classType.

const shapeGroup = this.add.group();

shapeGroup.add(this.add.circle(0, 0, 1));
const elfGroup = this.add.group();

elfGroup.add(new Elf(this, 0, 0, 'Yves'));

Groups as pools

In pooling you create game objects once and then recycle them as needed. Inactive game objects (also called dead or unused) are retrieved and reactivated when needed. Active game objects (also called alive or used) are deactivated when no longer needed. You will usually toggle a game object's visibility at the same time. In Arcade Physics groups, you should toggle body.enable as well.

You can use getFirstAlive(false) and getFirstDead(false) to select (not create) existing pool members that are active or inactive, respectively.

For creation/reactivation you usually use get(), which is a shortcut for getFirstDead(true).

console.log(
  '%s | size: %d | max: %d | active: %d | inactive: %d | used: %d | free: %d | full: %s',
  group.name,
  group.getLength(),
  group.maxSize,
  group.countActive(true),
  group.countActive(false),
  group.getTotalUsed(),
  group.getTotalFree(),
  group.isFull()
);

Physics groups

Clone this wiki locally