Мультиплеер в Construct 3
Плагин GamePush для Construct 3 включает движок автосинхронизации поверх мультиплеера GamePush. Вы один раз регистрируете объекты, которые нужно синхронизировать, запускаете авто-синк — и дальше плагин делает всё сам:
- собирает схему состояния из зарегистрированных объектов;
- каждый тик отправляет состояние ваших объектов;
- создаёт, обновляет и уничтожает копии объектов других игроков;
- создаёт у всех игроков объекты мира, которыми управляет хост;
- переживает миграцию хоста без потери объектов.
Писать код не нужно — всё настраивается действиями и условиями в листе событий. Если нужен низкоуровневый доступ, полный SDK доступен в скриптах через runtime.GamePush.multiplayer.
Общие принципы работы мультиплеера (хост и пиры, режимы синхронизации, интерполяция) описаны в разделе Мультиплеер — они полностью применимы и к Construct 3.
Как это устроено
Как и в SDK, в плагине есть три механизма синхронизации. В Construct 3 они выглядят так:
| Механизм | Действия в плагине | Для чего |
|---|---|---|
| Состояние игрока | Register object for sync со scope Player state | Аватар игрока: позиция, здоровье, скин. Каждый игрок управляет своим |
| Глобальное состояние | Register object for sync со scope Global state | Враги, предметы, окружение. Симулирует только хост, остальные видят копии |
| Сообщения | Send message / условие On message | Одноразовые события: выстрел, смерть, подбор предмета |
Ключевые термины:
- Тег — строковый идентификатор типа объекта в состоянии (например,
"player","enemy"). У каждого зарегистрированного объекта свой уникальный тег. - Локальный инстанс — ваш собственный экземпляр объекта со scope Player state. Его двигаете вы, остальные получают обновления.
- Прокси — экземпляр, который плагин автоматически создал у вас, чтобы показать объект другого игрока.
- Сущность (entity) — объект глобального состояния с сетевым ID (netId). Существует у хоста «по-настоящему», у остальных — в виде синхронизированной копии.
Быстрый старт
Порядок действий разработчика:
- Сделайте лобби на каналах: все игроки вступают в один канал.
- Подключитесь к мультиплееру действием
Connect. - На старте игровой сцены зарегистрируйте объекты и запустите авто-синк.
Подключение из лобби (например, хост нажимает «Старт» и все переходят на игровую сцену):
Легенда
Button_Start
GP_Channels
System
Button_Start — Объект Button (Кнопка)
GP_Channels›Плагин GamePush Channels
System›Системный объект Construct 3
Минимальная настройка синхронизации на игровой сцене:
Легенда
System
GP_Channels
MP_player
System›Системный объект Construct 3
GP_Channels›Плагин GamePush Channels
MP_player — Объект Sprite (Спрайт)
Этого достаточно, чтобы:
- ваш
MP_playerавтоматически отправлял позицию иhpкаждый тик; - у каждого игрока появились копии (прокси) игроков всех остальных;
- при выходе игрока его прокси автоматически уничтожился.
Все действия Register ... и Sync ... вызывайте до Start auto-sync. В момент запуска авто-синка плагин собирает схему состояния из всего, что зарегистрировано. Connect можно вызывать до или после — синхронизация начнётся, когда будут выполнены оба условия.
Синхронизация игрока
Регистрация объекта
Действие Multiplayer ▸ Register object for sync связывает тип объекта с мультиплеером:
| Параметр | Значение |
|---|---|
| Object | Тип объекта (Sprite и т. п.) |
| Tag | Уникальный тег в состоянии, например "player" |
| Scope | Player state — объектом управляет каждый игрок; Global state — объектами управляет хост |
| Transform | None, Position (x, y), Position + angle или Full (позиция, угол, размер, прозрачность, видимость) |
| Interpolate | Плавно интерполировать числовые поля трансформа (позицию, угол). Для телепортов и мгновенных перемещений отключите |
| Layer | Слой, на котором создавать копии у других игроков. Пусто — первый слой |
Переменные объекта
Действие Multiplayer ▸ Sync variable добавляет к синхронизации переменную экземпляра. Переменная выбирается из выпадающего списка — опечататься невозможно, и при переименовании переменной событие обновится само.
Включайте Interpolate только для чисел, которые должны меняться плавно. Строки и «мгновенные» значения (здоровье, ID предмета) оставляйте без интерполяции.
Легенда
System
GP_Channels
MP_player
System›Системный объект Construct 3
GP_Channels›Плагин GamePush Channels
MP_player — Объект Sprite (Спрайт)
Переменные синхронизируются в обе стороны автоматически: вы меняете переменную у своего объекта — у всех остальных она обновляется на прокси.
Внешний вид, анимации и меш
Три дополнительных действия расширяют синхронизацию зарегистрированного объекта:
- Sync appearance — чекбоксы: blend mode, цвет, flipped, mirrored, sampling, прозрачность, видимость.
- Sync animations — чекбоксы: имя анимации, кадр, скорость, repeat-to кадр. В большинстве игр достаточно имени и скорости — кадр синхронизируйте только если нужна точная покадровая синхронизация.
- Sync mesh — размер сетки и все её точки (позиция и текстурные координаты).
Легенда
System
GP_Channels
MP_player
System›Системный объект Construct 3
GP_Channels›Плагин GamePush Channels
MP_player — Объект Sprite (Спрайт)
Объём данных меша растёт с количеством точек: каждая точка — это 4 числа, отправляемых каждый тик при изменении. Используйте меши небольшого размера (например, 4×4) и только там, где это действительно нужно.
Свой инстанс и чужие прокси
Когда запускается авто-синк, плагин привязывает первый существующий экземпляр каждого player-объекта как ваш локальный. Если экземпляров несколько или объект создаётся позже, привяжите его явно действием Bind local instance (например, после перехода на новую сцену).
Отличить своего игрока от прокси можно по UID через выражение MultiplayerLocalPlayerUID:
Легенда
MP_player
System
MP_player — Объект Sprite (Спрайт)
System›Системный объект Construct 3
Тот же приём используйте, чтобы применять управление только к своему персонажу.
Прокси других игроков плагин создаёт и уничтожает сам. Если нужно повесить на них дополнительную логику (никнейм, полоску здоровья), используйте триггеры:
Легенда
GP_Channels
MP_player
System
NameTag
GP_Channels›Плагин GamePush Channels
MP_player — Объект Sprite (Спрайт)
System›Системный объект Construct 3
NameTag — Объект Text (Текст)
Внутри триггера доступны выражения MultiplayerProxyPlayerID, MultiplayerProxyTag и MultiplayerProxyUID.
Спавн игроков по точкам
Расставьте на сцене объекты MP_SpawnPoint и на старте расставьте по ним игроков. Позицию задаёт каждый игрок сам — своему локальному инстансу:
Легенда
System
MP_SpawnPoint
MP_player
System›Системный объект Construct 3
MP_SpawnPoint — Объект Sprite (Спрайт)
MP_player — Объект Sprite (Спрайт)
Синхронизация окружения с хоста
Объекты мира — враги, предметы, бочки — регистрируются со scope Global state. Ими управляет только хост:
- экземпляры, расставленные на сцене, у хоста автоматически становятся сущностями глобального состояния;
- у пиров расставленные на сцене копии заменяются синхронизированными сущностями — дубликатов не будет;
- объекты, которые хост создаёт во время игры, автоматически появляются у всех;
- объекты, которые хост уничтожает, исчезают у всех;
- при миграции хоста новый хост подхватывает последний снимок мира и продолжает симуляцию — делать ничего не нужно.
Легенда
System
GP_Channels
MP_enemy
MP_armor
System›Системный объект Construct 3
GP_Channels›Плагин GamePush Channels
MP_enemy — Объект Sprite (Спрайт)
MP_armor — Объект Sprite (Спрайт)
Логику мира (AI врагов, движение платформ) запускайте только на хосте — оберните её условием Is host:
Легенда
GP_Channels
System
MP_enemy
GP_Channels›Плагин GamePush Channels
System›Системный объект Construct 3
MP_enemy — Объект Sprite (Спрайт)
На пирах эти события просто не выполнятся, а позиции врагов придут по сети уже интерполированными.
Реагировать на появление и удаление сущностей можно триггерами:
Легенда
GP_Channels
MP_enemy
GP_Channels›Плагин GamePush Channels
MP_enemy — Объект Sprite (Спрайт)
Сообщения: стрельба, подбор предметов, смерти
Для одноразовых событий состояние не нужно — используйте Send message и условие On message. Параметры отправки:
- Event name — имя события, например
"shot"; - Data — строка данных (соберите значения через
&с разделителем); - Target player ID —
0для всех, ID игрока для конкретного адресата,MultiplayerHostPlayerID— только хосту; - Echo — получать ли собственное сообщение (удобно, чтобы обрабатывать выстрел одним событием у всех, включая стрелка).
Стрельба
Стреляющий отправляет координаты и угол, все (включая его самого, echo: Yes) создают пулю:
Легенда
Mouse
MP_player
GP_Channels
System
Bullet
Mouse — Объект Mouse (Мышь)
MP_player — Объект Sprite (Спрайт)
GP_Channels›Плагин GamePush Channels
System›Системный объект Construct 3
Bullet — Объект Sprite (Спрайт)
Кто выстрелил, определяется выражением MultiplayerCustomEventSenderID. Пулю саму по себе синхронизировать не нужно — каждый клиент просчитает её полёт локально, а урон авторитетно посчитает владелец цели или хост.
Подбор предмета
Предмет — глобальная сущность, уничтожить её может только хост. Игрок отправляет хосту запрос с netId предмета, хост уничтожает предмет, и тот исчезает у всех:
Легенда
MP_player
MP_armor
System
GP_Channels
MP_player — Объект Sprite (Спрайт)
MP_armor — Объект Sprite (Спрайт)
System›Системный объект Construct 3
GP_Channels›Плагин GamePush Channels
echo: Yes нужен на случай, когда подбирающий игрок сам является хостом.
Смерть и возрождение
Каждый игрок авторитетен для своего hp. Когда здоровье закончилось — сообщаем остальным и возрождаемся:
Легенда
MP_player
GP_Channels
MP_SpawnPoint
System
DeathFX
MP_player — Объект Sprite (Спрайт)
GP_Channels›Плагин GamePush Channels
MP_SpawnPoint — Объект Sprite (Спрайт)
System›Системный объект Construct 3
DeathFX — Объект Sprite (Спрайт)
Справочник: Действия
| Действие | Что делает | Пример использования | Важные замечания |
|---|---|---|---|
| Multiplayer ▸ Connect | Подключиться к комнате мультиплеера по ID канала | В лобби после входа в канал: Connect to channel Channels.ChannelID | Игрок должен быть участником канала. Выбор хоста занимает несколько секунд после подключения |
| Multiplayer ▸ Disconnect | Отключиться от комнаты | При выходе в меню | Прокси других игроков будут уничтожены |
| Multiplayer ▸ Set mode | Выбрать режим синхронизации: Fast (60 tick) или Smooth (20 tick) | Fast — для шутеров и гонок, Smooth — для стратегий и медленных игр | Задавайте до Start auto-sync. По умолчанию — Smooth |
| Multiplayer ▸ Send message | Отправить событие другим игрокам: имя, данные, адресат (0 — всем, ID — конкретному), echo | Выстрел: Send "shot" with data X & ":" & Y to 0, echo Yes | Не передавайте через сообщения постоянно меняющиеся координаты — для этого есть состояние |
| Multiplayer ▸ Register object for sync | Связать тип объекта с синхронизацией: тег, scope (Player/Global state), transform-пресет, интерполяция, слой | Register MP_player as "player" in Player state | Вызывайте до Start auto-sync. Тег должен быть уникальным |
| Multiplayer ▸ Sync variable | Добавить переменную экземпляра к синхронизации (выбор из списка) | Sync variable hp of MP_player (interpolate: False) | После Register object, до Start auto-sync. Интерполяция — только для плавно меняющихся чисел |
| Multiplayer ▸ Sync appearance | Синхронизировать внешний вид: blend mode, цвет, flipped, mirrored, sampling, прозрачность, видимость | Скрывать подобранное оружие у всех: галочки Opacity и Visible | Прозрачность и видимость уже входят в transform-пресет Full — не дублируйте |
| Multiplayer ▸ Sync animations | Синхронизировать анимацию спрайта: имя, кадр, скорость, repeat-to кадр | Анимации бега/прыжка персонажа: галочки Name и Speed | Кадр включайте только для точной покадровой синхронизации — это лишний трафик |
| Multiplayer ▸ Sync mesh | Синхронизировать деформацию меша: размер сетки и все точки | Развевающийся флаг, деформируемое желе | Трафик растёт с размером меша — используйте маленькие сетки |
| Multiplayer ▸ Start auto-sync | Собрать схемы из зарегистрированных объектов и запустить автосинхронизацию | Последним действием в блоке настройки на старте сцены | После запуска новые Register ... не попадут в схему |
| Multiplayer ▸ Stop auto-sync | Остановить циклы автосинхронизации | При выходе из игровой сцены в меню | Соединение с комнатой сохраняется |
| Multiplayer ▸ Bind local instance | Явно привязать пикнутый экземпляр как локальный объект игрока | После перехода на новую сцену или если экземпляров несколько | По умолчанию привязывается первый экземпляр автоматически |
Справочник: Условия
| Условие | Тип | Что проверяет / когда срабатывает | Важные замечания |
|---|---|---|---|
| Multiplayer ▸ On connect | Триггер | Подключение к комнате выполнено | Хост на этот момент может быть ещё не выбран |
| Multiplayer ▸ On connect error | Триггер | Подключение не удалось | Текст ошибки — в выражении GamePushChannels.LastError |
| Multiplayer ▸ On disconnect | Триггер | Отключение от комнаты | |
| Multiplayer ▸ On disconnect error | Триггер | Отключение завершилось ошибкой | |
| Multiplayer ▸ Is connected | Обычное | Игрок подключён к комнате | |
| Multiplayer ▸ Is host | Обычное | Текущий игрок — хост | Используйте как гейт для AI и мировой логики. Роль может смениться в любой момент |
| Multiplayer ▸ On became host | Триггер | Текущий игрок стал хостом | Срабатывает и при первом выборе хоста, и при миграции |
| Multiplayer ▸ On became peer | Триггер | Текущий игрок стал пиром | |
| Multiplayer ▸ On host migrated | Триггер | Хост в комнате сменился | Авто-синк переживает миграцию сам, обычно ничего делать не нужно |
| Multiplayer ▸ On player joined | Триггер | Игрок вошёл в комнату | Прокси нового игрока создастся автоматически, когда придёт его состояние |
| Multiplayer ▸ On player left | Триггер | Игрок покинул комнату | Его прокси уничтожится автоматически |
| Multiplayer ▸ On players updated | Триггер | Список подключённых игроков обновился | Для списков игроков в UI |
| Multiplayer ▸ Each connected player | Цикл | Перебор подключённых игроков | Внутри доступны MultiplayerCurPlayerID, MultiplayerCurPlayerPing и др. |
| Multiplayer ▸ On message | Триггер | Получено сообщение. Фильтр по имени события; пустое имя — любые сообщения | Данные — MultiplayerCustomEventData, отправитель — MultiplayerCustomEventSenderID |
| Multiplayer ▸ On tick | Триггер | Каждый сетевой тик SDK (20 или 60 в секунду) | Для игровой логики с фиксированным шагом. Дельта — MultiplayerLastTickDelta |
| Multiplayer ▸ On send state error | Триггер | Отправка состояния не удалась | |
| Multiplayer ▸ Is auto-sync active | Обычное | Авто-синк запущен (Start auto-sync выполнен) | |
| Multiplayer ▸ On entity created | Триггер | Появилась глобальная сущность (создана хостом) | Пикайте экземпляр по MultiplayerEntityUID |
| Multiplayer ▸ On entity destroyed | Триггер | Глобальная сущность удалена | Экземпляр уничтожается сразу после триггера — успейте создать эффекты |
| Multiplayer ▸ On player proxy created | Триггер | Локально создан объект другого игрока | Пикайте по MultiplayerProxyUID; ID игрока — MultiplayerProxyPlayerID |
| Multiplayer ▸ On player proxy destroyed | Триггер | Объект другого игрока сейчас будет уничтожен | |
| Multiplayer ▸ On global state updated | Триггер | Пришло обновление глобального состояния (только на пирах) | Продвинутый сценарий: авто-синк уже применяет состояние к объектам сам |
| Multiplayer ▸ For each entity | Цикл | Перебор синхронизированных сущностей с тегом | Внутри доступны MultiplayerEntityId, MultiplayerEntityUID, MultiplayerEntityField |
Справочник: Выражения
Все выражения вызываются через объект плагина, например GamePushChannels.MultiplayerMyPlayerID.
Подключение и игроки
| Выражение | Возвращает | Пример |
|---|---|---|
MultiplayerMyPlayerID | ID текущего игрока | Подпись над своим персонажем |
MultiplayerHostPlayerID | ID текущего хоста (0, если хост не выбран) | Адресат Send message, чтобы написать только хосту |
MultiplayerConnectedPlayersCount | Число подключённых игроков | "Игроков: " & GamePushChannels.MultiplayerConnectedPlayersCount |
MultiplayerConnectedPlayersAsJSON | Массив подключённых игроков как JSON-строка | Для разбора объектом JSON |
MultiplayerNetworkPing | Текущий пинг в мс | Индикатор качества соединения |
MultiplayerTickRate | Текущий tick rate (20 или 60) | |
MultiplayerBufferSize | Размер буфера интерполяции (количество снимков) | Отладка |
MultiplayerBufferDelay | Задержка буфера интерполяции в мс | Отладка |
MultiplayerLastTickDelta | Дельта последнего тика в мс | Движение с фиксированным шагом внутри On tick |
Внутри цикла Each connected player
| Выражение | Возвращает |
|---|---|
MultiplayerCurPlayerID | ID игрока в цикле |
MultiplayerCurPlayerState("key") | Поле состояния игрока в цикле |
MultiplayerCurPlayerIsHost | 1, если игрок в цикле — хост, иначе 0 |
MultiplayerCurPlayerPing | Пинг игрока в цикле, мс |
MultiplayerCurPlayerConnectionStability | Стабильность соединения 0–1 |
MultiplayerCurPlayerSessionDuration | Время игрока в комнате, мс |
Состояние
| Выражение | Возвращает | Пример |
|---|---|---|
MultiplayerMyState | Состояние текущего игрока как JSON-строка | Отладка |
MultiplayerMyStateKey("key") | Поле собственного состояния. Поддерживает точечные пути | MultiplayerMyStateKey("hp") |
MultiplayerPlayerState(id, "key") | Поле состояния любого игрока по ID | MultiplayerPlayerState(2, "hp") |
MultiplayerPlayersStateAsJSON | Карта состояний всех игроков как JSON-строка | Отладка |
MultiplayerGlobalStateAsJSON | Полное глобальное состояние как JSON-строка | Отладка |
Сообщения (внутри On message)
| Выражение | Возвращает |
|---|---|
MultiplayerCustomEventName | Имя последнего сообщения |
MultiplayerCustomEventSenderID | ID отправителя последнего сообщения |
MultiplayerCustomEventData | Данные последнего сообщения |
Сущности и прокси
| Выражение | Возвращает | Пример |
|---|---|---|
MultiplayerEntityId | netId текущей сущности (в For each entity / On entity created) | |
MultiplayerEntityUID | UID экземпляра текущей сущности | С условием Pick instance with UID |
MultiplayerEntityTag | Тег текущей сущности | |
MultiplayerEntityType | Имя типа объекта текущей сущности | |
MultiplayerEntityField("key") | Поле текущей сущности | MultiplayerEntityField("hp") |
MultiplayerEntityIdForUID(uid) | netId сущности по UID экземпляра | Данные для запроса на подбор предмета |
MultiplayerEntityUIDForId("netId") | UID экземпляра по netId | Пикнуть предмет на хосте по netId из сообщения |
MultiplayerEntityCount("tag") | Количество сущностей с тегом | MultiplayerEntityCount("enemy") |
MultiplayerLocalPlayerUID("tag") | UID вашего локального экземпляра для тега | Отличить своего персонажа: Pick instance with UID |
MultiplayerPlayerProxyUID(playerId, "tag") | UID прокси-экземпляра игрока | Найти персонажа игрока по его ID |
MultiplayerProxyPlayerID | ID игрока текущего прокси (в On player proxy created/destroyed) | |
MultiplayerProxyTag | Тег текущего прокси | |
MultiplayerProxyUID | UID текущего прокси | С условием Pick instance with UID |
Оставайтесь на связи
С другими документами раздела вы можете ознакомиться здесь. Для начала работы с GamePush ознакомьтесь с нашими туториалами.
Сообщество GamePush в Telegram: @gs_community.
Для ваших обращений e-mail: official@gamepush.com
Желаем вам успехов!