groups-and-containers
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGroups 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: , ,
Related skills: ../sprites-and-images/SKILL.md, ../physics-arcade/SKILL.md
src/gameobjects/group/src/gameobjects/container/src/gameobjects/layer/逻辑分组(Group)、带变换继承的视觉分组(Container)、渲染层分组(Layer)、对象池,以及在Phaser 4中各自的适用场景。
核心源码路径: , ,
相关技能: ../sprites-and-images/SKILL.md, ../physics-arcade/SKILL.md
src/gameobjects/group/src/gameobjects/container/src/gameobjects/layer/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
| 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 | | | 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 | | | |
| 特性 | Group | Container | Layer |
|---|---|---|---|
| 用途 | 逻辑集合 / 对象池 | 带变换功能的视觉父容器 | 渲染顺序桶 |
| 是否在显示列表中 | 否(子对象在) | 是(渲染其子对象) | 是(渲染其子对象) |
| 位置/旋转/缩放 | 无 | 有(子对象继承) | 无 |
| 子对象存储 | | | List(Structs.List) |
| 物理系统支持 | 通过physics.add.group()实现 | 有限(若不在(0,0)位置会有偏移) | 无 |
| 输入支持 | 无(子对象可单独支持) | 是(需要设置碰撞区域形状) | 无 |
| 对象池功能 | 是(getFirstDead、kill等方法) | 无 | 无 |
| 遮罩支持 | 无 | 是(Canvas渲染下不支持子对象单独遮罩) | 是 |
| 透明度/混合模式/可见性 | 无(可通过setVisible批量设置) | 是 | 是 |
| 嵌套支持 | 不适用 | 支持Container嵌套 | 无法放入Container中 |
| 继承自 | EventEmitter | GameObject | List |
| 创建方法 | | | |
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 to override).
setExclusive(false)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 nullPool helper methods on Group:
| Method | Description |
|---|---|
| Shortcut: |
| First member matching active |
| First member where |
| First member where |
| Like getFirst but searches back-to-front |
| Sets |
| Sets |
| Count members where |
| Count of active members |
| |
| True if |
核心对象池模式:停用对象而非销毁,之后重用非激活对象。
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的对象池辅助方法:
| 方法 | 描述 |
|---|---|
| 快捷方式: |
| 查找第一个匹配active状态的成员 |
| 查找第一个active===true的成员 |
| 查找第一个active===false的成员 |
| 类似getFirst,但从后往前搜索 |
| 将成员设置为active=false |
| 将成员设置为active=false和visible=false |
| 统计active===value的成员数量(默认值为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:
| Method | Description |
|---|---|
| Add Game Object(s); removes from display list |
| Remove; optionally destroy |
| Access by index |
| Query children |
| Filtered access and counting |
| Ordering |
| Iteration (iterate passes index) |
| Pass true to also apply to children |
| Bounding rect of all children |
| World point to local space |
| When false, children can exist in multiple places |
| Swap one child for another |
| Set hit area size (required for input) |
| 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核心方法:
| 方法 | 描述 |
|---|---|
| 添加游戏对象;会将其从显示列表中移除 |
| 移除对象;可选择是否销毁 |
| 通过索引访问子对象 |
| 查询子对象 |
| 过滤访问和统计 |
| 排序 |
| 遍历(iterate会传递索引) |
| 传入true可同时应用于子对象 |
| 获取所有子对象的边界矩形 |
| 将世界坐标转换为容器局部坐标 |
| 设置为false时,子对象可存在于多个容器中 |
| 替换子对象 |
| 设置碰撞区域大小(输入交互所需) |
| 只读属性,子对象数量 |
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 groupjs
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、setTintContainer (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
注意事项
-
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.
-
Container has performance overhead. Every child requires extra matrix math per frame. Deep nesting multiplies this. Avoid Containers when a Group or Layer suffices.
-
Container origin is always 0,0. The transform point cannot be changed. Position children relative to (0,0).
-
Container children lose Scene-level depth control. A child'sonly orders within the Container. The Container's own depth positions it in the Scene.
depth -
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.
-
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.
-
Group.get() vs Group.getFirst() differ.is shorthand for
get(x, y)-- finds first inactive member and creates if none found.getFirst(false, true, x, y)defaults togetFirst(state)without auto-creating.active===false -
Layer cannot go inside a Container. Containers can be added to Layers, but not the reverse.
-
Group children Set is unordered. No index-based access. Useto get an array snapshot.
getChildren() -
killAndHide does not remove from the group. It only setsand
active=false. The object stays in the group for reuse.visible=false -
Container.setScrollFactor does not auto-propagate. Passas the third argument to also update children:
true.container.setScrollFactor(0, 0, true) -
Group.create() adds to the Scene display list. Butdoes NOT unless you pass
group.add()as the second argument.true -
Container needs setSize() for input. Containers have no implicit size. You must callbefore
container.setSize(width, height)will work with a hit area.setInteractive()
-
Group不在显示列表中。其子对象单独出现在Scene的显示列表中。移动Group不会产生视觉变化——需要此功能请使用Container。
-
Container有性能开销。每个子对象每帧都需要额外的矩阵运算。嵌套越深开销越大。不需要变换时优先使用Group或Layer。
-
Container的原点始终为(0,0)。变换点无法更改。请相对于(0,0)定位子对象。
-
Container的子对象失去Scene级别的depth控制。子对象的仅在Container内部排序。Container自身的depth决定其在Scene中的位置。
depth -
物理系统+Container存在问题。如果Container不在(0,0)位置,子对象的物理刚体会出现偏移。避免在Container的子对象上使用物理刚体。
-
Canvas渲染下Container的子对象无法单独设置遮罩。只有Container本身可设置遮罩。嵌套Container的遮罩不会叠加。WebGL渲染下遮罩可叠加。
-
Group.get()与Group.getFirst()不同。是
get(x, y)的简写——查找第一个非激活成员,若不存在则创建。getFirst(false, true, x, y)默认查找active===false的成员,且不会自动创建。getFirst(state) -
Layer无法放入Container中。Container可添加到Layer中,但反之不行。
-
Group的子对象Set集合是无序的。不支持基于索引的访问。使用获取数组快照。
getChildren() -
killAndHide不会将对象从Group中移除。它仅设置和
active=false。对象仍留在Group中以便重用。visible=false -
Container.setScrollFactor不会自动传递给子对象。需传入第三个参数true来同时更新子对象:。
container.setScrollFactor(0, 0, true) -
Group.create()会将对象添加到Scene显示列表中。但不会,除非传入第二个参数true。
group.add() -
Container需要调用setSize()才能支持输入。Container没有默认大小。必须调用后,
container.setSize(width, height)才能配合碰撞区域正常工作。setInteractive()
Source File Map
源码文件映射
| File | Description |
|---|---|
| Group class -- pooling, create, getFirst*, kill, batch ops |
| |
| GroupConfig typedef (classType, maxSize, callbacks) |
| GroupCreateConfig typedef (key, quantity, setXY, etc.) |
| Container class -- list management, nested transforms |
| |
| Container WebGL/Canvas render functions |
| Layer class -- display list bucket with alpha/blend/mask |
| |
| Layer WebGL/Canvas render functions |
| |
| 文件 | 描述 |
|---|---|
| Group类——对象池、创建、getFirst*、kill、批量操作 |
| |
| GroupConfig类型定义(classType、maxSize、回调) |
| GroupCreateConfig类型定义(key、quantity、setXY等) |
| Container类——列表管理、嵌套变换 |
| |
| Container的WebGL/Canvas渲染函数 |
| Layer类——带透明度/混合模式/遮罩的显示列表桶 |
| |
| Layer的WebGL/Canvas渲染函数 |
| |