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()