Плагины: глобальные и сценарные

Система плагинов в Phaser предназначена для расширения базовой функциональности движка без изменения его исходного кода. Плагины позволяют внедрять новые менеджеры, сервисы, инструменты обработки данных, игровые механики и интеграции с внешними API.

В архитектуре Phaser различаются два типа плагинов:

  • Глобальные (Global Plugins)
  • Сценарные (Scene Plugins)

Различие между ними заключается в области действия, жизненном цикле и способе доступа к функциональности.


Глобальные плагины

Назначение

Глобальный плагин подключается на уровне всего игрового экземпляра и доступен во всех сценах. Он создаётся один раз и существует на протяжении всей жизни объекта Phaser.Game.

Такой подход подходит для:

  • систем аналитики;
  • менеджеров сохранений;
  • сетевых клиентов;
  • общих сервисов (например, управление аудио, профилями игроков);
  • централизованных логгеров.

Регистрация глобального плагина

Глобальные плагины регистрируются в конфигурации игры:

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    plugins: {
        global: [
            {
                key: 'MyGlobalPlugin',
                plugin: MyGlobalPlugin,
                start: true
            }
        ]
    }
};

const game = new Phaser.Game(config);

Ключевые параметры:

  • key — имя плагина для доступа через менеджер плагинов.
  • plugin — класс плагина.
  • start — запуск сразу после инициализации.

Структура глобального плагина

Глобальный плагин наследуется от Phaser.Plugins.BasePlugin:

class MyGlobalPlugin extends Phaser.Plugins.BasePlugin {

    constructor(pluginManager) {
        super(pluginManager);
    }

    init() {
        // вызывается при инициализации
    }

    start() {
        // вызывается при старте
    }

    stop() {
        // вызывается при остановке
    }

    destroy() {
        // очистка ресурсов
        super.destroy();
    }
}

Жизненный цикл

Глобальный плагин проходит следующие этапы:

  1. Конструктор — создание экземпляра.
  2. init() — инициализация.
  3. start() — активация.
  4. stop() — временная остановка.
  5. destroy() — окончательное удаление.

Методы start и stop позволяют временно отключать функциональность без уничтожения объекта.

Доступ к глобальному плагину

Получение экземпляра из сцены:

const plugin = this.plugins.get('MyGlobalPlugin');
plugin.someMethod();

this.plugins — это менеджер плагинов сцены, который имеет доступ к глобальным плагинам.


Сценарные плагины

Назначение

Сценарный плагин создаётся отдельно для каждой сцены. Он уничтожается вместе со сценой и не существует за её пределами.

Подходит для:

  • специфических игровых механик;
  • кастомных менеджеров объектов;
  • локальных UI-систем;
  • расширений логики сцены.

Регистрация сценарного плагина

Регистрация происходит в конфигурации:

const config = {
    plugins: {
        scene: [
            {
                key: 'MyScenePlugin',
                plugin: MyScenePlugin,
                mapping: 'myPlugin'
            }
        ]
    }
};

Параметр mapping автоматически добавляет ссылку на плагин в объект сцены:

this.myPlugin.doSomething();

Структура сценарного плагина

Сценарный плагин наследуется от Phaser.Plugins.ScenePlugin:

class MyScenePlugin extends Phaser.Plugins.ScenePlugin {

    constructor(scene, pluginManager) {
        super(scene, pluginManager);
    }

    boot() {
        // вызывается при запуске сцены
    }

    start() {
        // когда сцена становится активной
    }

    stop() {
        // при остановке сцены
    }

    destroy() {
        super.destroy();
    }
}

Особенности жизненного цикла

Жизненный цикл тесно связан с жизненным циклом сцены:

  • boot() — сцена загружается.
  • start() — сцена активируется.
  • stop() — сцена выключается.
  • destroy() — сцена уничтожается.

Каждая новая сцена получает свой экземпляр плагина, что гарантирует изоляцию состояния.


Сравнение глобальных и сценарных плагинов

Характеристика Глобальный Сценарный
Область действия Вся игра Конкретная сцена
Количество экземпляров Один По одному на сцену
Жизненный цикл Связан с Game Связан со Scene
Подходит для Общих сервисов Локальной логики

Принцип выбора

  • Если требуется единый источник данных для всей игры — используется глобальный плагин.
  • Если логика ограничена одной сценой — применяется сценарный.

Взаимодействие с менеджером плагинов

Phaser использует PluginManager, который управляет регистрацией и доступом к плагинам.

Внутри сцены доступны:

  • this.plugins — менеджер плагинов сцены.
  • this.sys.plugins — системный доступ к менеджеру.

Пример динамического добавления:

this.plugins.installScenePlugin(
    'DynamicPlugin',
    DynamicPlugin,
    'dynamic',
    this
);

Такой способ позволяет подключать расширения во время выполнения.


Передача данных в плагин

Глобальные плагины могут получать данные через метод init(data):

plugins: {
    global: [
        {
            key: 'ConfigurablePlugin',
            plugin: ConfigurablePlugin,
            data: { debug: true }
        }
    ]
}

Внутри плагина:

init(data) {
    this.debug = data.debug;
}

Сценарные плагины получают доступ к сцене через this.scene, что позволяет использовать:

  • загрузчик ресурсов;
  • менеджер объектов;
  • камеру;
  • физику;
  • события сцены.

Расширение API сцены

Сценарный плагин может добавлять собственные методы в объект сцены:

class UtilityPlugin extends Phaser.Plugins.ScenePlugin {

    boot() {
        this.scene.customMethod = () => {
            console.log('Custom logic');
        };
    }
}

После регистрации метод становится частью интерфейса сцены.


Работа с событиями

Плагины активно используют событийную систему Phaser.

Пример подписки в глобальном плагине:

start() {
    this.game.events.on('pause', this.onPause, this);
}

В сценарном плагине:

boot() {
    this.scene.events.on('shutdown', this.cleanup, this);
}

Корректное удаление подписок в destroy() обязательно для предотвращения утечек памяти.


Практический пример: глобальный менеджер сохранений

class SaveManager extends Phaser.Plugins.BasePlugin {

    save(key, data) {
        localStorage.setItem(key, JSON.stringify(data));
    }

    load(key) {
        const data = localStorage.getItem(key);
        return data ? JSON.parse(data) : null;
    }
}

Использование:

this.plugins.get('SaveManager').save('player', { score: 100 });

Такой подход обеспечивает централизованный доступ к хранилищу.


Практический пример: сценарный менеджер спавна

class SpawnPlugin extends Phaser.Plugins.ScenePlugin {

    spawn(x, y, texture) {
        return this.scene.add.sprite(x, y, texture);
    }
}

Использование:

this.spawnPlugin.spawn(100, 200, 'enemy');

Каждая сцена управляет собственными объектами без конфликтов с другими сценами.


Производительность и управление памятью

При разработке плагинов необходимо учитывать:

  • удаление слушателей событий;
  • освобождение ссылок на объекты;
  • избегание хранения ссылок на уничтоженные сцены;
  • контроль глобального состояния.

Глобальные плагины особенно чувствительны к утечкам памяти, так как существуют на протяжении всей игры.


Организация структуры проекта

Рекомендуется размещать плагины в отдельной директории:

/plugins
    Global/
    Scene/

И экспортировать их как модули ES6:

export default class MyPlugin extends Phaser.Plugins.ScenePlugin { }

Это упрощает масштабирование и поддержку проекта.


Расширенные возможности

Плагины могут:

  • внедрять собственные события;
  • оборачивать API Phaser;
  • предоставлять сервис-локаторы;
  • внедрять зависимости;
  • взаимодействовать с внешними библиотеками;
  • реализовывать архитектурные паттерны (Singleton, Service, Facade).

Гибкость системы плагинов делает её одним из ключевых инструментов построения масштабируемых игровых приложений на Phaser.