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.
What this skill does
# 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
```js
// In a Scene's create() method:
// --- Group: logical collection, no transform, great for pooling ---
const enemies = this.add.group();
enemies.create(100, 200, 'enemy'); // creates Sprite at (100,200)
enemies.create(300, 200, 'enemy');
// --- Container: visual parent with inherited transform ---
const hud = this.add.container(10, 10);
const icon = this.add.image(0, 0, 'heart');
const label = this.add.text(20, 0, 'x3');
hud.add([icon, label]); // children move/scale/rotate with hud
// --- Layer: render-ordering bucket, no position/scale ---
const bgLayer = this.add.layer();
const fgLayer = this.add.layer();
bgLayer.add(this.add.image(400, 300, 'sky'));
fgLayer.add(this.add.sprite(400, 300, 'player'));
```
## 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
```js
// Empty group, add existing objects
const gems = this.add.group();
gems.add(existingSprite);
gems.addMultiple([sprite1, sprite2, sprite3]);
// Group with config -- creates children automatically
const coins = this.add.group({
classType: Phaser.GameObjects.Sprite,
key: 'coin',
quantity: 10, // overrides frameQuantity
setXY: { x: 50, y: 300, stepX: 60 },
setScale: { x: 0.5, y: 0.5 }
});
// Custom class type with pool limit
const bullets = this.add.group({
classType: Bullet, // must accept (scene, x, y, key, frame)
maxSize: 30,
defaultKey: 'bullet',
runChildUpdate: true // calls child.update() each frame
});
```
### Object Pooling with getFirstDead
The core pooling pattern: deactivate objects instead of destroying them, then reuse inactive ones.
```js
// Setup pool
const bullets = this.add.group({
classType: Phaser.GameObjects.Sprite,
defaultKey: 'bullet',
maxSize: 30
});
// Fire a bullet -- get() finds first inactive member or creates one
function fireBullet(x, y) {
const bullet = bullets.get(x, y);
if (bullet) {
bullet.setActive(true);
bullet.setVisible(true);
bullet.body.velocity.y = -300; // if physics enabled
}
}
// Deactivate when off-screen or on hit
function killBullet(bullet) {
bullets.killAndHide(bullet); // sets active=false, visible=false
// If using physics, also reset the body:
// bullet.body.stop();
}
// Alternative: manual getFirst
const inactive = bullets.getFirst(false); // first where active===false
const active = bullets.getFirstAlive(); // first where active===true
const dead = bullets.getFirstDead(true, x, y); // first inactive, create if null
```
**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.
```js
// Arcade Physics group -- every member gets a dynamic body
const enemies = this.physics.add.group({
key: 'enemy',
quantity: 5,
setXY: { x: 100, y: 100, stepX: 80 }
});
// Static physics group -- immovable bodies
const platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground');
// Collide physics groups with each other
this.physics.add.collider(player, platforms);
this.physics.add.overlap(bullets, enemies, onHit);
```
### Containers with Nested Transforms
```js
// HUD that follows camera
const hud = this.add.container(10, 10);
hud.setScrollFactor(0); // pinned to camera
const healthBar = this.add.rectangle(0, 0, 200, 20, 0x00ff00);
const healthText = this.add.text(210, -5, '100 HP');
hud.add([healthBar, healthText]);
// Move everything at once
hud.setPosition(50, 50);
// Scale and rotate propagate to children
hud.setScale(1.5);
hud.setRotation(0.1);
// Alpha affects all children
hud.setAlpha(0.8);
// Nested containers
const inventory = this.add.container(300, 500);
for (let i = 0; i < 5; i++) {
const slot = this.add.container(i * 55, 0);
slot.add([
this.add.rectangle(0, 0, 48, 48, 0x333333),
this.add.image(0, 0, `item-${i}`)
]);
inventory.add(slot); // Container inside Container
}
```
**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)` / `getFirRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.