Object pooling — это метод управления объектами в
играх, направленный на уменьшение нагрузки на сборщик мусора и повышение
производительности. В Phaser 3 для реализации пулов объектов
используется система групп
(Phaser.GameObjects.Group), которая позволяет
управлять множеством однотипных игровых объектов с возможностью их
повторного использования.
При создании группы можно задать максимальный размер пула
(maxSize). Этот параметр ограничивает количество
активных объектов и позволяет контролировать ресурсы.
const bullets = this.add.group({
classType: Phaser.GameObjects.Image,
maxSize: 20,
runChildUpdate: true
});
Пояснения:
classType — класс объектов, которые будут содержаться в
группе. В примере используется Phaser.GameObjects.Image, но
можно указать любой кастомный класс.maxSize — максимальное количество объектов в пуле. При
попытке получить новый объект после достижения лимита метод
get() вернёт null.runChildUpdate — если true, метод
update() каждого объекта группы будет вызываться
автоматически при каждом кадре сцены.Для извлечения объекта используется метод get():
const bullet = bullets.get(x, y, 'bulletTexture');
if (bullet) {
bullet.setActive(true);
bullet.setVisible(true);
bullet.body.velocity.y = -300;
}
Важно:
maxSize, get() вернёт
null. Это предотвращает создание лишних объектов.get(), изначально
неактивны и невидимы. Для их использования необходимо явно включить
видимость и активность через setActive(true) и
setVisible(true).После того как объект завершил своё назначение, его нужно вернуть в
пул с помощью killAndHide() или через
setActive(false)/setVisible(false):
bullet.killAndHide();
bullet.body.stop();
killAndHide() — удобный метод, который отключает объект
и скрывает его из сцены.Группы поддерживают следующие свойства и методы, которые облегчают работу с объектами:
countActive(true/false) — возвращает
количество активных или неактивных объектов.getFirstDead() — получает первый
неактивный объект из пула.preUpdate(time, delta) — вызывается
автоматически при runChildUpdate: true для всех объектов
группы.add() / remove() —
динамическое добавление и удаление объектов из группы.Пример динамического использования:
this.time.addEvent({
delay: 200,
loop: true,
callback: () => {
const bullet = bullets.get();
if (bullet) {
bullet.setPosition(player.x, player.y - 20);
bullet.setActive(true);
bullet.setVisible(true);
bullet.body.velocity.y = -400;
}
}
});
Для более сложного поведения часто создают собственные классы
объектов и передают их в classType группы. Это позволяет
автоматически инициализировать объекты при извлечении из пула.
class Bullet extends Phaser.GameObjects.Image {
constructor(scene, x, y) {
super(scene, x, y, 'bulletTexture');
scene.add.existing(this);
scene.physics.add.existing(this);
this.body.setCollideWorldBounds(true);
this.setActive(false);
this.setVisible(false);
}
fire(x, y) {
this.setPosition(x, y);
this.setActive(true);
this.setVisible(true);
this.body.velocity.y = -300;
}
update() {
if (this.y < -50) {
this.setActive(false);
this.setVisible(false);
}
}
}
const bullets = this.add.group({
classType: Bullet,
maxSize: 30,
runChildUpdate: true
});
Теперь пул управляет объектами полностью: каждый объект сам
обрабатывает своё возвращение в пул, а сцена получает только ссылку на
готовый объект через get().
maxSize.get(), чтобы избежать
ошибок при достижении лимита.runChildUpdate: true при необходимости
автоматической логики объектов.Использование групп с maxSize в Phaser является
оптимальным подходом для современных 2D-игр, где важны
производительность и стабильность. Пулы объектов обеспечивают
эффективное управление ресурсами и позволяют создавать плавный игровой
процесс даже при большом количестве динамических элементов.