groups-and-containers

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Groups and Containers

Groups与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
逻辑分组(Group)、带变换继承的视觉分组(Container)、渲染层分组(Layer)、对象池,以及在Phaser 4中各自的适用场景。
核心源码路径:
src/gameobjects/group/
,
src/gameobjects/container/
,
src/gameobjects/layer/
相关技能: ../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'));
js
// 在Scene的create()方法中:

// --- Group:逻辑集合,无变换功能,非常适合对象池 ---
const enemies = this.add.group();
enemies.create(100, 200, 'enemy');       // 在(100,200)位置创建Sprite
enemies.create(300, 200, 'enemy');

// --- Container:带变换继承的视觉父容器 ---
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]);                  // 子对象会随hud一起移动/缩放/旋转

// --- Layer:渲染顺序桶,无位置/缩放属性 ---
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

Group vs Container vs Layer

FeatureGroupContainerLayer
PurposeLogical collection / poolVisual parent with transformRender-order bucket
On display listNo (children are)Yes (renders children)Yes (renders children)
Position/rotation/scaleNoYes (children inherit)No
Children storage
children
(Set)
list
(Array)
List (Structs.List)
PhysicsVia physics.add.group()Limited (offsets if not at 0,0)No
InputNo (children can)Yes (needs hit area shape)No
Object poolingYes (getFirstDead, kill)NoNo
MasksNoYes (not per-child in Canvas)Yes
Alpha/blend/visibleNo (batch via setVisible)YesYes
NestingN/AContainer in ContainerCannot go in Container
ExtendsEventEmitterGameObjectList
Factory
this.add.group()
this.add.container(x, y)
this.add.layer()
特性GroupContainerLayer
用途逻辑集合 / 对象池带变换功能的视觉父容器渲染顺序桶
是否在显示列表中否(子对象在)是(渲染其子对象)是(渲染其子对象)
位置/旋转/缩放有(子对象继承)
子对象存储
children
(Set集合)
list
(数组)
List(Structs.List)
物理系统支持通过physics.add.group()实现有限(若不在(0,0)位置会有偏移)
输入支持无(子对象可单独支持)是(需要设置碰撞区域形状)
对象池功能是(getFirstDead、kill等方法)
遮罩支持是(Canvas渲染下不支持子对象单独遮罩)
透明度/混合模式/可见性无(可通过setVisible批量设置)
嵌套支持不适用支持Container嵌套无法放入Container中
继承自EventEmitterGameObjectList
创建方法
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.
Group: 管理同类对象集合(敌人、子弹、金币)、带激活/非激活生命周期的对象池、物理组碰撞。无共享视觉变换。成员可同时属于多个Group。
Container: 子对象继承位置、旋转、缩放、透明度。用于复合UI元素(生命值条、物品栏槽位)、作为整体移动/旋转的对象集群、嵌套变换。默认是独占模式——一个子对象只能属于一个Container(可使用
setExclusive(false)
取消独占)。
Layer: 控制对象批次的渲染顺序,应用共享的透明度/混合模式/遮罩。无位置/缩放/旋转属性。轻量级渲染分组。

Container vs Group at a Glance

Container与Group快速对比

  • 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.
  • Container拥有位置、旋转、缩放、透明度属性——Group没有。如果需要子对象作为整体移动/旋转,请使用Container。
  • Container默认独占——添加子对象会将其从之前的Container中移除。Group是非独占的;一个游戏对象可属于多个Group。
  • Container在显示列表中——它会渲染其子对象。Group不在显示列表中;其子对象单独在Scene中渲染。
  • Group支持对象池——包含getFirstDead、kill、killAndHide等方法。Container不支持。
  • Container有性能开销——每个子对象每帧都需要额外的矩阵运算。嵌套越深开销越大。不需要变换时优先使用Group或Layer。

Common Patterns

常见模式

Creating and Populating Groups

创建并填充Group

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
});
js
// 空Group,添加已有对象
const gems = this.add.group();
gems.add(existingSprite);
gems.addMultiple([sprite1, sprite2, sprite3]);

// 带配置的Group——自动创建子对象
const coins = this.add.group({
    classType: Phaser.GameObjects.Sprite,
    key: 'coin',
    quantity: 10,           // 覆盖frameQuantity
    setXY: { x: 50, y: 300, stepX: 60 },
    setScale: { x: 0.5, y: 0.5 }
});

// 带池限制的自定义类类型
const bullets = this.add.group({
    classType: Bullet,       // 必须接受(scene, x, y, key, frame)参数
    maxSize: 30,
    defaultKey: 'bullet',
    runChildUpdate: true     // 每帧调用child.update()
});

Object Pooling with getFirstDead

使用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:
MethodDescription
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
核心对象池模式:停用对象而非销毁,之后重用非激活对象。
js
// 设置对象池
const bullets = this.add.group({
    classType: Phaser.GameObjects.Sprite,
    defaultKey: 'bullet',
    maxSize: 30
});

// 发射子弹——get()方法找到第一个非激活成员,若不存在则创建
function fireBullet(x, y) {
    const bullet = bullets.get(x, y);

    if (bullet) {
        bullet.setActive(true);
        bullet.setVisible(true);
        bullet.body.velocity.y = -300;   // 若启用物理系统
    }
}

// 子弹离开屏幕或命中目标时停用
function killBullet(bullet) {
    bullets.killAndHide(bullet);         // 设置active=false,visible=false
    // 若使用物理系统,还需重置刚体:
    // bullet.body.stop();
}

// 替代方案:手动调用getFirst
const inactive = bullets.getFirst(false);     // 第一个active===false的成员
const active = bullets.getFirstAlive();       // 第一个active===true的成员
const dead = bullets.getFirstDead(true, x, y); // 第一个非激活成员,若不存在则创建
Group的对象池辅助方法:
方法描述
get(x, y, key, frame)
快捷方式:
getFirst(false, true, ...)
——查找非激活成员或创建新成员
getFirst(state, createIfNull, x, y, key, frame)
查找第一个匹配active状态的成员
getFirstAlive(createIfNull, x, y, key, frame)
查找第一个active===true的成员
getFirstDead(createIfNull, x, y, key, frame)
查找第一个active===false的成员
getLast(state, createIfNull, x, y, key, frame)
类似getFirst,但从后往前搜索
kill(gameObject)
将成员设置为active=false
killAndHide(gameObject)
将成员设置为active=false和visible=false
countActive(value)
统计active===value的成员数量(默认值为true)
getTotalUsed()
激活成员的数量
getTotalFree()
maxSize - 激活成员数
(剩余池容量)
isFull()
children.size >= maxSize
时返回true

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);
物理组继承自Group,可自动分配刚体。详见../physics-arcade/SKILL.md的完整说明。
js
// Arcade物理组——每个成员都会获得一个动态刚体
const enemies = this.physics.add.group({
    key: 'enemy',
    quantity: 5,
    setXY: { x: 100, y: 100, stepX: 80 }
});

// 静态物理组——不可移动的刚体
const platforms = this.physics.add.staticGroup();
platforms.create(400, 568, 'ground');

// 让物理组之间发生碰撞
this.physics.add.collider(player, platforms);
this.physics.add.overlap(bullets, enemies, onHit);

Containers with Nested Transforms

带嵌套变换的Container

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:
MethodDescription
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
js
// 跟随相机的HUD
const hud = this.add.container(10, 10);
hud.setScrollFactor(0);     // 固定在相机上

const healthBar = this.add.rectangle(0, 0, 200, 20, 0x00ff00);
const healthText = this.add.text(210, -5, '100 HP');
hud.add([healthBar, healthText]);

// 一次性移动所有内容
hud.setPosition(50, 50);

// 缩放和旋转会传递给子对象
hud.setScale(1.5);
hud.setRotation(0.1);

// 透明度会影响所有子对象
hud.setAlpha(0.8);

// 嵌套Container
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嵌套在Container中
}
Container核心方法:
方法描述
add(child)
/
addAt(child, index)
添加游戏对象;会将其从显示列表中移除
remove(child, destroyChild)
移除对象;可选择是否销毁
getAt(index)
/
getIndex(child)
通过索引访问子对象
getByName(name)
/
getFirst(prop, val)
查询子对象
getAll(prop, val)
/
count(prop, val)
过滤访问和统计
sort(property)
/
swap(a, b)
/
moveTo(child, idx)
排序
each(cb, ctx)
/
iterate(cb, ctx)
遍历(iterate会传递索引)
setScrollFactor(x, y, updateChildren)
传入true可同时应用于子对象
getBounds(output)
获取所有子对象的边界矩形
pointToContainer(source, output)
将世界坐标转换为容器局部坐标
setExclusive(value)
设置为false时,子对象可存在于多个容器中
replace(oldChild, newChild)
替换子对象
setSize(width, height)
设置碰撞区域大小(输入交互所需)
length
只读属性,子对象数量

Layers for Render Ordering

使用Layer控制渲染顺序

js
const bgLayer = this.add.layer();
const entityLayer = this.add.layer();
const uiLayer = this.add.layer();

// Add objects -- they render in layer order, then by depth within layer
bgLayer.add(this.add.image(400, 300, 'sky'));
entityLayer.add(player);
entityLayer.add(enemy);
uiLayer.add(scoreText);

// Control depth of layers themselves
bgLayer.setDepth(0);
entityLayer.setDepth(1);
uiLayer.setDepth(2);

// Children set depth within their layer
enemy.setDepth(5);   // relative to entityLayer, not the Scene

// Apply shared effects to entire layer
entityLayer.setAlpha(0.5);
entityLayer.setVisible(false);
entityLayer.setBlendMode(Phaser.BlendModes.ADD);
js
const bgLayer = this.add.layer();
const entityLayer = this.add.layer();
const uiLayer = this.add.layer();

// 添加对象——按Layer顺序渲染,同一Layer内按depth排序
bgLayer.add(this.add.image(400, 300, 'sky'));
entityLayer.add(player);
entityLayer.add(enemy);
uiLayer.add(scoreText);

// 控制Layer自身的depth
bgLayer.setDepth(0);
entityLayer.setDepth(1);
uiLayer.setDepth(2);

// 子对象在所属Layer内设置depth
enemy.setDepth(5);   // 相对于entityLayer,而非Scene

// 为整个Layer应用共享效果
entityLayer.setAlpha(0.5);
entityLayer.setVisible(false);
entityLayer.setBlendMode(Phaser.BlendModes.ADD);

Bulk Creation with createMultiple

使用createMultiple批量创建

js
// createMultiple accepts a GroupCreateConfig or array of them
const coins = this.add.group();

coins.createMultiple({
    key: 'coin',
    quantity: 20,
    setXY: { x: 50, y: 100, stepX: 40, stepY: 0 },
    setScale: { x: 0.5, y: 0.5 },
    setRotation: { value: 0, step: 0.1 },   // each rotated 0.1 more than previous
    setAlpha: { value: 1 },
    setOrigin: { x: 0.5, y: 0.5 },
    setDepth: { value: 5 },
    gridAlign: {
        width: 5,
        height: 4,
        cellWidth: 48,
        cellHeight: 48,
        x: 100,
        y: 200
    }
});

// Multiple configs at once (creates two different sets)
coins.createMultiple([
    { key: 'gold-coin', quantity: 10, setXY: { x: 50, y: 100, stepX: 30 } },
    { key: 'silver-coin', quantity: 10, setXY: { x: 50, y: 200, stepX: 30 } }
]);
js
// createMultiple接受GroupCreateConfig或其数组
const coins = this.add.group();

coins.createMultiple({
    key: 'coin',
    quantity: 20,
    setXY: { x: 50, y: 100, stepX: 40, stepY: 0 },
    setScale: { x: 0.5, y: 0.5 },
    setRotation: { value: 0, step: 0.1 },   // 每个对象比前一个多旋转0.1
    setAlpha: { value: 1 },
    setOrigin: { x: 0.5, y: 0.5 },
    setDepth: { value: 5 },
    gridAlign: {
        width: 5,
        height: 4,
        cellWidth: 48,
        cellHeight: 48,
        x: 100,
        y: 200
    }
});

// 同时使用多个配置(创建两组不同的对象)
coins.createMultiple([
    { key: 'gold-coin', quantity: 10, setXY: { x: 50, y: 100, stepX: 30 } },
    { key: 'silver-coin', quantity: 10, setXY: { x: 50, y: 200, stepX: 30 } }
]);

Iterating and Batch Operations on Groups

Group的遍历与批量操作

js
const enemies = this.add.group();

// Get all children as array
const all = enemies.getChildren();
const active = enemies.getMatching('active', true);

// Batch property operations
enemies.setXY(200, 300);
enemies.incX(5);                    // add 5 to each member's x
enemies.setVisible(false);
enemies.propertyValueSet('tintTopLeft', 0xff0000);
enemies.playAnimation('walk');

// Stepping: apply incremental values across members
enemies.setX(100, 50);             // first at x=100, next at 150, then 200...
enemies.setY(200, 30);             // first at y=200, next at 230, then 260...
enemies.setXY(100, 200, 50, 30);   // combined X and Y stepping
enemies.incXY(10, 5);              // add 10 to each x, 5 to each y
enemies.angle(0, 15);              // first at 0 deg, next at 15, then 30...
enemies.setAlpha(1, -0.1);         // first at 1.0, next at 0.9, then 0.8...
enemies.setScale(1, 0, 0.1, 0);   // scaleX: 1.0, 1.1, 1.2... (stepX=0.1)
enemies.setDepth(0, 1);            // depth 0, 1, 2, 3...
enemies.setOrigin(0.5);
enemies.setBlendMode(Phaser.BlendModes.ADD);
enemies.setTint(0xff0000);
enemies.shuffle();                  // randomize order in the group
js
const enemies = this.add.group();

// 将所有子对象转为数组
const all = enemies.getChildren();
const active = enemies.getMatching('active', true);

// 批量属性操作
enemies.setXY(200, 300);
enemies.incX(5);                    // 每个成员的x坐标加5
enemies.setVisible(false);
enemies.propertyValueSet('tintTopLeft', 0xff0000);
enemies.playAnimation('walk');

// 步进式操作:为成员应用递增的值
enemies.setX(100, 50);             // 第一个x=100,下一个x=150,以此类推...
enemies.setY(200, 30);             // 第一个y=200,下一个y=230,以此类推...
enemies.setXY(100, 200, 50, 30);   // 同时设置X和Y的步进值
enemies.incXY(10, 5);              // 每个成员x加10,y加5
enemies.angle(0, 15);              // 第一个角度0度,下一个15度,以此类推...
enemies.setAlpha(1, -0.1);         // 第一个透明度1.0,下一个0.9,以此类推...
enemies.setScale(1, 0, 0.1, 0);   // scaleX:1.0, 1.1, 1.2...(stepX=0.1)
enemies.setDepth(0, 1);            // depth依次为0,1,2,3...
enemies.setOrigin(0.5);
enemies.setBlendMode(Phaser.BlendModes.ADD);
enemies.setTint(0xff0000);
enemies.shuffle();                  // 随机打乱Group内的顺序

API Quick Reference

API快速参考

Group (Phaser.GameObjects.Group)

Group(Phaser.GameObjects.Group)

Factory:  this.add.group(children?, config?)

Config types:
  GroupConfig       -- classType, name, active, maxSize, defaultKey, defaultFrame,
                       runChildUpdate, createCallback, removeCallback
  GroupCreateConfig -- key (required), classType, frame, quantity, visible, active,
                       repeat, yoyo, frameQuantity, max, setXY, setRotation,
                       setScale, setOrigin, setAlpha, setDepth, setScrollFactor,
                       hitArea, gridAlign

Key members:  children (Set), classType, maxSize, defaultKey, defaultFrame,
              active, runChildUpdate
Lifecycle:    create, createMultiple, add, addMultiple, remove, clear, destroy
Queries:      getFirst, getFirstAlive, getFirstDead, getLast, get, getChildren,
              getLength, getMatching, contains, countActive, getTotalUsed,
              getTotalFree, isFull
Pool:         get, getFirstDead, kill, killAndHide
Bulk ops:     setX/Y/XY, incX/Y/XY, setAlpha, setVisible, toggleVisible,
              playAnimation, propertyValueSet, propertyValueInc, setOrigin,
              setDepth, shuffle, setBlendMode, setTint
创建方法:  this.add.group(children?, config?)

配置类型:
  GroupConfig       -- classType、name、active、maxSize、defaultKey、defaultFrame、
                       runChildUpdate、createCallback、removeCallback
  GroupCreateConfig -- key(必填)、classType、frame、quantity、visible、active、
                       repeat、yoyo、frameQuantity、max、setXY、setRotation、
                       setScale、setOrigin、setAlpha、setDepth、setScrollFactor、
                       hitArea、gridAlign

核心成员:  children(Set集合)、classType、maxSize、defaultKey、defaultFrame、
              active、runChildUpdate
生命周期:    create、createMultiple、add、addMultiple、remove、clear、destroy
查询方法:      getFirst、getFirstAlive、getFirstDead、getLast、get、getChildren、
              getLength、getMatching、contains、countActive、getTotalUsed、
              getTotalFree、isFull
对象池方法:         get、getFirstDead、kill、killAndHide
批量操作:     setX/Y/XY、incX/Y/XY、setAlpha、setVisible、toggleVisible、
              playAnimation、propertyValueSet、propertyValueInc、setOrigin、
              setDepth、shuffle、setBlendMode、setTint

Container (Phaser.GameObjects.Container)

Container(Phaser.GameObjects.Container)

Factory:  this.add.container(x?, y?, children?)

Extends:  GameObject
Mixins:   AlphaSingle, BlendMode, ComputedSize, Depth, Mask, Transform, Visible

Key members:  list (Array), exclusive, maxSize, scrollFactorX/Y
Children:     add, addAt, remove, removeAt, removeBetween, removeAll
Queries:      getAt, getIndex, getByName, getFirst, getAll, getRandom, count
Ordering:     sort, swap, moveTo, moveUp, moveDown, sendToBack, bringToTop,
              moveAbove, moveBelow, reverse
Transform:    pointToContainer, getBounds, getBoundsTransformMatrix
Iteration:    each(cb, ctx), iterate(cb, ctx, ...args)
Config:       setExclusive, setScrollFactor(x, y, updateChildren)
Property:     length (read-only child count)
创建方法:  this.add.container(x?, y?, children?)

继承自:  GameObject
混入:   AlphaSingle、BlendMode、ComputedSize、Depth、Mask、Transform、Visible

核心成员:  list(数组)、exclusive、maxSize、scrollFactorX/Y
子对象操作:     add、addAt、remove、removeAt、removeBetween、removeAll
查询方法:      getAt、getIndex、getByName、getFirst、getAll、getRandom、count
排序:     sort、swap、moveTo、moveUp、moveDown、sendToBack、bringToTop、
              moveAbove、moveBelow、reverse
变换:    pointToContainer、getBounds、getBoundsTransformMatrix
遍历:    each(cb, ctx)、iterate(cb, ctx, ...args)
配置:       setExclusive、setScrollFactor(x, y, updateChildren)
属性:     length(只读,子对象数量)

Layer (Phaser.GameObjects.Layer)

Layer(Phaser.GameObjects.Layer)

Factory:  this.add.layer(children?)

Extends:  Phaser.Structs.List
Mixins:   AlphaSingle, BlendMode, Depth, Filters, Mask, RenderSteps, Visible

Key members:  scene, displayList, sortChildrenFlag
Children:     add, remove (inherited from List)
Settings:     setAlpha, setBlendMode, setDepth, setVisible, setMask, setName,
              setActive, setState, setData, getData

No position, rotation, scale, scroll factor, input, or physics.
Cannot be added to a Container. Containers can be added to Layers.
创建方法:  this.add.layer(children?)

继承自:  Phaser.Structs.List
混入:   AlphaSingle、BlendMode、Depth、Filters、Mask、RenderSteps、Visible

核心成员:  scene、displayList、sortChildrenFlag
子对象操作:     add、remove(继承自List)
设置:     setAlpha、setBlendMode、setDepth、setVisible、setMask、setName、
              setActive、setState、setData、getData

无位置、旋转、缩放、滚动系数、输入或物理系统支持。
无法添加到Container中。但Container可添加到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.
  1. Group不在显示列表中。其子对象单独出现在Scene的显示列表中。移动Group不会产生视觉变化——需要此功能请使用Container。
  2. Container有性能开销。每个子对象每帧都需要额外的矩阵运算。嵌套越深开销越大。不需要变换时优先使用Group或Layer。
  3. Container的原点始终为(0,0)。变换点无法更改。请相对于(0,0)定位子对象。
  4. Container的子对象失去Scene级别的depth控制。子对象的
    depth
    仅在Container内部排序。Container自身的depth决定其在Scene中的位置。
  5. 物理系统+Container存在问题。如果Container不在(0,0)位置,子对象的物理刚体会出现偏移。避免在Container的子对象上使用物理刚体。
  6. Canvas渲染下Container的子对象无法单独设置遮罩。只有Container本身可设置遮罩。嵌套Container的遮罩不会叠加。WebGL渲染下遮罩可叠加。
  7. Group.get()与Group.getFirst()不同
    get(x, y)
    getFirst(false, true, x, y)
    的简写——查找第一个非激活成员,若不存在则创建。
    getFirst(state)
    默认查找active===false的成员,且不会自动创建。
  8. Layer无法放入Container中。Container可添加到Layer中,但反之不行。
  9. Group的子对象Set集合是无序的。不支持基于索引的访问。使用
    getChildren()
    获取数组快照。
  10. killAndHide不会将对象从Group中移除。它仅设置
    active=false
    visible=false
    。对象仍留在Group中以便重用。
  11. Container.setScrollFactor不会自动传递给子对象。需传入第三个参数true来同时更新子对象:
    container.setScrollFactor(0, 0, true)
  12. Group.create()会将对象添加到Scene显示列表中。但
    group.add()
    不会,除非传入第二个参数true。
  13. Container需要调用setSize()才能支持输入。Container没有默认大小。必须调用
    container.setSize(width, height)
    后,
    setInteractive()
    才能配合碰撞区域正常工作。

Source File Map

源码文件映射

FileDescription
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()
文件描述
src/gameobjects/group/Group.js
Group类——对象池、创建、getFirst*、kill、批量操作
src/gameobjects/group/GroupFactory.js
this.add.group()
工厂注册
src/gameobjects/group/typedefs/GroupConfig.js
GroupConfig类型定义(classType、maxSize、回调)
src/gameobjects/group/typedefs/GroupCreateConfig.js
GroupCreateConfig类型定义(key、quantity、setXY等)
src/gameobjects/container/Container.js
Container类——列表管理、嵌套变换
src/gameobjects/container/ContainerFactory.js
this.add.container()
工厂注册
src/gameobjects/container/ContainerRender.js
Container的WebGL/Canvas渲染函数
src/gameobjects/layer/Layer.js
Layer类——带透明度/混合模式/遮罩的显示列表桶
src/gameobjects/layer/LayerFactory.js
this.add.layer()
工厂注册
src/gameobjects/layer/LayerRender.js
Layer的WebGL/Canvas渲染函数
src/physics/arcade/ArcadePhysics.js
this.physics.add.group()
/
staticGroup()