groups-and-containers
Use this skill when using Groups or Containers in Phaser 4. Covers organizing game objects, object pooling, batch operations, and nested transforms with Containers. Triggers on: Group, Container, object pool, getFirstDead, children.
By phaserjs · 521 installs
npx skills add phaserjs/phaser --skill groups-and-containers
Source repository · Upstream listing
Groups and Containers
Logical grouping (Group), visual grouping with transform inheritance (Container), render layer grouping (Layer), object pooling, and when to use each in Phaser 4.
Key source paths: src/gameobjects/group/ , src/gameobjects/container/ , src/gameobjects/layer/
Related skills: ../sprites and images/SKILL.md, ../physics arcade/SKILL.md
Quick Start
Core Concepts
Group vs Container vs Layer
Feature Group Container Layer
Purpose Logical collection / pool Visual parent with transform Render order bucket
On display list No (children are) Yes (renders children) Yes (renders children)
Position/rotation/scale No Yes (children inherit) No
Children storage children (Set) list (Array) List (Structs.List)
Physics Via physics.add.group() Limited (offsets if not at 0,0) No
Input No (children can) Yes (needs hit area shape) No
Object pooling Yes (getFirstDead, kill) No No
Masks No Yes (not per child in Canvas) Yes
Alpha/blend/visible No (batch via setVisible) Yes Yes
Nesting N/A Container in Container Cannot go in Container
Extends EventEmitter GameObject List
Factory this.add.group() this.add.container(x, y) this.add.layer()
When to Use Each
Group: Managing collections of similar objects (enemies, bullets, coins), object pooling with active/inactive lifecycle, physics group collisions. No shared visual transform. Members can belong to multiple Groups simultaneously.
Container: Children inherit position, rotation, scale, alpha. Composite UI elements (health bars, inventory slots), moving/rotating clusters as one unit, nested transforms. By default exclusive a child can only belong to one Container (use setExclusive(false) to override).
Layer: Controlling render order of object batches, applying shared alpha/blend/mask. No position/scale/rotation. Lightweight render bucketing.
Container vs Group at a Glance
Container has position, rotation, scale, alpha Group does not. If you need children to move/rotate as a unit, use Container.
Container is exclusive by default adding a child removes it from its previous Container. Group is non exclusive; a game object can be in many Groups.
Container is on the display list it renders its children. Group is not on the display list; its children render individually on the Scene.
Group supports object pooling getFirstDead, kill, killAndHide. Container does not.
Container has performance cost each child requires matrix math per frame. Deeper nesting = more cost. Prefer Group or Layer when transforms are not needed.
Common Patterns
Creating and Populating Groups
Object Pooling with getFirstDead
The core pooling pattern: deactivate objects instead of destroying them, then reuse inactive ones.
Pool helper methods on Group:
Method Description
get(x, y, key, frame) Shortcut: getFirst(false, true, ...) finds inactive or creates
getFirst(state, createIfNull, x, y, key, frame) First member matching active state
getFirstAlive(createIfNull, x, y, key, frame) First member where active===true
getFirstDead(createIfNull, x, y, key, frame) First member where active===false
getLast(state, createIfNull, x, y, key, frame) Like getFirst but searches back to front
kill(gameObject) Sets active=false on a member
killAndHide(gameObject) Sets active=false and visible=false
countActive(value) Count members where active===value (default true)
getTotalUsed() Count of active members
getTotalFree() maxSize active count (remaining pool capacity)
isFull() True if children.size = maxSize
Physics Groups
Physics groups extend Group with automatic body assignment. See ../physics arcade/SKILL.md for full details.
Containers with Nested Transforms
Key Container methods:
Method Description
add(child) / addAt(child, index) Add Game Object(s); removes from display list
remove(child, destroyChild) Remove; optionally destroy
getAt(index) / getIndex(child) Access by index
getByName(name) / getFirst(prop, val) Query children
getAll(prop, val) / count(prop, val) Filtered access and counting
sort(property) / swap(a, b) / moveTo(child, idx) Ordering
each(cb, ctx) / iterate(cb, ctx) Iteration (iterate passes index)
setScrollFactor(x, y, updateChildren) Pass true to also apply to children
getBounds(output) Bounding rect of all children
pointToContainer(source, output) World point to local space
setExclusive(value) When false, children can exist in multiple places
replace(oldChild, newChild) Swap one child for another
setSize(width, height) Set hit area size (required for input)
length Read only child count
Layers for Render Ordering
Bulk Creation with createMultiple
Iterating and Batch Operations on Groups
API Quick Reference
Group (Phaser.GameObjects.Group)
Container (Phaser.GameObjects.Container)
Layer (Phaser.GameObjects.Layer)
Gotchas
1. Group is NOT on the display list. Its children appear on the Scene display list individually. Moving a Group does nothing visually use Container for that.
2. Container has performance overhead. Every child requires extra matrix math per frame. Deep nesting multiplies this. Avoid Containers when a Group or Layer suffices.
3. Container origin is always 0,0. The transform point cannot be changed. Position children relative to (0,0).
4. Container children lose Scene level depth control. A child's depth only orders within the Container. The Container's own depth positions it in the Scene.
5. Physics + Container is problematic. If a Container is not at (0,0), physics bodies on children will be offset. Avoid physics bodies on Container children.
6. Container children cannot be individually masked in Canvas rendering. Only the Container itself can have a mask. Masks do not stack for nested Containers. Masks do stack in WebGL rendering.
7. Group.get() vs Group.getFirst() differ. get(x, y) is shorthand for getFirst(false, true, x, y) finds first inactive member and creates if none found. getFirst(state) defaults to active===false without auto creating.
8. Layer cannot go inside a Container. Containers can be added to Layers, but not the reverse.
9. Group children Set is unordered. No index based access. Use getChildren() to get an array snapshot.
10. killAndHide does not remove from the group. It only sets active=false and visible=false . The object stays in the group for reuse.
11. Container.setScrollFactor does not auto propagate. Pass true as the third argument to also update children: container.setScrollFactor(0, 0, true) .
12. Group.create() adds to the Scene display list. But group.add() does NOT unless you pass true as the second argument.
13. Container needs setSize() for input. Containers have no implicit size. You must call container.setSize(width, height) before setInteractive() will work with a hit area.
Source File Map
File Description
src/gameobjects/group/Group.js Group class pooling, create, getFirst , kill, batch ops
src/gameobjects/group/GroupFactory.js this.add.group() factory registration
src/gameobjects/group/typedefs/GroupConfig.js GroupConfig typedef (classType, maxSize, callbacks)
src/gameobjects/group/typedefs/GroupCreateConfig.js GroupCreateConfig typedef (key, quantity, setXY, etc.)
src/gameobjects/container/Container.js Container class list management, nested transforms
src/gameobjects/container/ContainerFactory.js this.add.container() factory registration
src/gameobjects/container/ContainerRender.js Container WebGL/Canvas render functions
src/gameobjects/layer/Layer.js Layer class display list bucket with alpha/blend/mask
src/gameobjects/layer/LayerFactory.js this.add.layer() factory registration
src/gameobjects/layer/LayerRender.js Layer WebGL/Canvas render functions
src/physics/arcade/ArcadePhysics.js this.physics.add.group() / staticGroup()