Перейти к основному содержимому
🎉 GP CONF 2026: Конференция о рынке WEB-игр 👾 23 сентября | Подробнее

Мультиплеер в 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). Существует у хоста «по-настоящему», у остальных — в виде синхронизированной копии.

Быстрый старт

Порядок действий разработчика:

  1. Сделайте лобби на каналах: все игроки вступают в один канал.
  2. Подключитесь к мультиплееру действием Connect.
  3. На старте игровой сцены зарегистрируйте объекты и запустите авто-синк.

Подключение из лобби (например, хост нажимает «Старт» и все переходят на игровую сцену):

Лист событий: Lobby
Button_Start
On clicked
GP_Channels
Multiplayer: Connect to channel Channels.ChannelID
GP_Channels
Multiplayer: On connect
System
Go to Game
ЛегендаButton_StartGP_ChannelsSystem

Минимальная настройка синхронизации на игровой сцене:

Лист событий: Game
System
On start of layout
GP_Channels
Multiplayer: Register MP_player as "player" in Player state state (transform: Position (x, y), interpolate: True, layer: "game")
GP_Channels
Multiplayer: Sync variable hp of MP_player (interpolate: False)
GP_Channels
Multiplayer: Set mode Fast (60 tick)
GP_Channels
Multiplayer: Start auto-sync
ЛегендаSystemGP_ChannelsMP_player

Этого достаточно, чтобы:

  • ваш MP_player автоматически отправлял позицию и hp каждый тик;
  • у каждого игрока появились копии (прокси) игроков всех остальных;
  • при выходе игрока его прокси автоматически уничтожился.
Порядок важен

Все действия Register ... и Sync ... вызывайте до Start auto-sync. В момент запуска авто-синка плагин собирает схему состояния из всего, что зарегистрировано. Connect можно вызывать до или после — синхронизация начнётся, когда будут выполнены оба условия.

Синхронизация игрока

Регистрация объекта

Действие Multiplayer ▸ Register object for sync связывает тип объекта с мультиплеером:

ПараметрЗначение
ObjectТип объекта (Sprite и т. п.)
TagУникальный тег в состоянии, например "player"
ScopePlayer state — объектом управляет каждый игрок; Global state — объектами управляет хост
TransformNone, Position (x, y), Position + angle или Full (позиция, угол, размер, прозрачность, видимость)
InterpolateПлавно интерполировать числовые поля трансформа (позицию, угол). Для телепортов и мгновенных перемещений отключите
LayerСлой, на котором создавать копии у других игроков. Пусто — первый слой

Переменные объекта

Действие Multiplayer ▸ Sync variable добавляет к синхронизации переменную экземпляра. Переменная выбирается из выпадающего списка — опечататься невозможно, и при переименовании переменной событие обновится само.

Включайте Interpolate только для чисел, которые должны меняться плавно. Строки и «мгновенные» значения (здоровье, ID предмета) оставляйте без интерполяции.

System
On start of layout
GP_Channels
Multiplayer: Sync variable hp of MP_player (interpolate: False)
GP_Channels
Multiplayer: Sync variable weapon of MP_player (interpolate: False)
GP_Channels
Multiplayer: Sync variable skin of MP_player (interpolate: False)
ЛегендаSystemGP_ChannelsMP_player

Переменные синхронизируются в обе стороны автоматически: вы меняете переменную у своего объекта — у всех остальных она обновляется на прокси.

Внешний вид, анимации и меш

Три дополнительных действия расширяют синхронизацию зарегистрированного объекта:

  • Sync appearance — чекбоксы: blend mode, цвет, flipped, mirrored, sampling, прозрачность, видимость.
  • Sync animations — чекбоксы: имя анимации, кадр, скорость, repeat-to кадр. В большинстве игр достаточно имени и скорости — кадр синхронизируйте только если нужна точная покадровая синхронизация.
  • Sync mesh — размер сетки и все её точки (позиция и текстурные координаты).
System
On start of layout
GP_Channels
Multiplayer: Sync appearance of MP_player (blend: False, color: False, flipped: False, mirrored: True, sampling: False, opacity: True, visible: True)
GP_Channels
Multiplayer: Sync animations of MP_player (name: True, frame: False, speed: True, repeat-to: False)
ЛегендаSystemGP_ChannelsMP_player
Sync mesh и трафик

Объём данных меша растёт с количеством точек: каждая точка — это 4 числа, отправляемых каждый тик при изменении. Используйте меши небольшого размера (например, 4×4) и только там, где это действительно нужно.

Свой инстанс и чужие прокси

Когда запускается авто-синк, плагин привязывает первый существующий экземпляр каждого player-объекта как ваш локальный. Если экземпляров несколько или объект создаётся позже, привяжите его явно действием Bind local instance (например, после перехода на новую сцену).

Отличить своего игрока от прокси можно по UID через выражение MultiplayerLocalPlayerUID:

MP_player
Pick instance with UID GamePushChannels.MultiplayerLocalPlayerUID("player")
System
Scroll to MP_player
ЛегендаMP_playerSystem
  • MP_playerОбъект Sprite (Спрайт)
  • SystemСистемный объект Construct 3

Тот же приём используйте, чтобы применять управление только к своему персонажу.

Прокси других игроков плагин создаёт и уничтожает сам. Если нужно повесить на них дополнительную логику (никнейм, полоску здоровья), используйте триггеры:

GP_Channels
Multiplayer: On player proxy created
+ Add action
MP_player
Pick instance with UID GamePushChannels.MultiplayerProxyUID
System
Create object NameTag on layer "ui" at (MP_player.X, MP_player.Y - 40)
ЛегендаGP_ChannelsMP_playerSystemNameTag
  • GP_ChannelsПлагин GamePush Channels
  • MP_playerОбъект Sprite (Спрайт)
  • SystemСистемный объект Construct 3
  • NameTagОбъект Text (Текст)

Внутри триггера доступны выражения MultiplayerProxyPlayerID, MultiplayerProxyTag и MultiplayerProxyUID.

Спавн игроков по точкам

Расставьте на сцене объекты MP_SpawnPoint и на старте расставьте по ним игроков. Позицию задаёт каждый игрок сам — своему локальному инстансу:

System
On start of layout
+ Add action
MP_SpawnPoint
Pick random instance
MP_player
Pick instance with UID GamePushChannels.MultiplayerLocalPlayerUID("player")
MP_player
Set position to (MP_SpawnPoint.X, MP_SpawnPoint.Y)
ЛегендаSystemMP_SpawnPointMP_player
  • SystemСистемный объект Construct 3
  • MP_SpawnPointОбъект Sprite (Спрайт)
  • MP_playerОбъект Sprite (Спрайт)

Синхронизация окружения с хоста

Объекты мира — враги, предметы, бочки — регистрируются со scope Global state. Ими управляет только хост:

  • экземпляры, расставленные на сцене, у хоста автоматически становятся сущностями глобального состояния;
  • у пиров расставленные на сцене копии заменяются синхронизированными сущностями — дубликатов не будет;
  • объекты, которые хост создаёт во время игры, автоматически появляются у всех;
  • объекты, которые хост уничтожает, исчезают у всех;
  • при миграции хоста новый хост подхватывает последний снимок мира и продолжает симуляцию — делать ничего не нужно.
System
On start of layout
GP_Channels
Multiplayer: Register MP_enemy as "enemy" in Global state state (transform: Position (x, y), interpolate: True, layer: "game")
GP_Channels
Multiplayer: Sync variable hp of MP_enemy (interpolate: False)
GP_Channels
Multiplayer: Register MP_armor as "armor" in Global state state (transform: Position (x, y), interpolate: True, layer: "game")
ЛегендаSystemGP_ChannelsMP_enemyMP_armor
  • SystemСистемный объект Construct 3
  • GP_ChannelsПлагин GamePush Channels
  • MP_enemyОбъект Sprite (Спрайт)
  • MP_armorОбъект Sprite (Спрайт)

Логику мира (AI врагов, движение платформ) запускайте только на хосте — оберните её условием Is host:

GP_Channels
Multiplayer: Is host
+ Add action
System
For each MP_enemy
MP_enemy
Simulate Platform pressing Left
ЛегендаGP_ChannelsSystemMP_enemy

На пирах эти события просто не выполнятся, а позиции врагов придут по сети уже интерполированными.

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

GP_Channels
Multiplayer: On entity created
+ Add action
MP_enemy
Pick instance with UID GamePushChannels.MultiplayerEntityUID
MP_enemy
Start Fade behavior
ЛегендаGP_ChannelsMP_enemy

Сообщения: стрельба, подбор предметов, смерти

Для одноразовых событий состояние не нужно — используйте Send message и условие On message. Параметры отправки:

  • Event name — имя события, например "shot";
  • Data — строка данных (соберите значения через & с разделителем);
  • Target player ID0 для всех, ID игрока для конкретного адресата, MultiplayerHostPlayerID — только хосту;
  • Echo — получать ли собственное сообщение (удобно, чтобы обрабатывать выстрел одним событием у всех, включая стрелка).

Стрельба

Стреляющий отправляет координаты и угол, все (включая его самого, echo: Yes) создают пулю:

Mouse
On Left button Clicked
+ Add action
MP_player
Pick instance with UID GamePushChannels.MultiplayerLocalPlayerUID("player")
GP_Channels
Multiplayer: Send "shot" with data MP_player.X & ":" & MP_player.Y & ":" & MP_player.Angle to 0, echo Yes
GP_Channels
Multiplayer: On message "shot"
System
Create object Bullet on layer "game" at (float(tokenat(GamePushChannels.MultiplayerCustomEventData, 0, ":")), float(tokenat(GamePushChannels.MultiplayerCustomEventData, 1, ":")))
Bullet
Set Bullet angle of motion to float(tokenat(GamePushChannels.MultiplayerCustomEventData, 2, ":")) degrees
ЛегендаMouseMP_playerGP_ChannelsSystemBullet
  • MouseОбъект Mouse (Мышь)
  • MP_playerОбъект Sprite (Спрайт)
  • GP_ChannelsПлагин GamePush Channels
  • SystemСистемный объект Construct 3
  • BulletОбъект Sprite (Спрайт)

Кто выстрелил, определяется выражением MultiplayerCustomEventSenderID. Пулю саму по себе синхронизировать не нужно — каждый клиент просчитает её полёт локально, а урон авторитетно посчитает владелец цели или хост.

Подбор предмета

Предмет — глобальная сущность, уничтожить её может только хост. Игрок отправляет хосту запрос с netId предмета, хост уничтожает предмет, и тот исчезает у всех:

MP_player
On collision with MP_armor
System
Compare: MP_player.UID = GamePushChannels.MultiplayerLocalPlayerUID("player")
GP_Channels
Multiplayer: Send "pickupArmor" with data GamePushChannels.MultiplayerEntityIdForUID(MP_armor.UID) to GamePushChannels.MultiplayerHostPlayerID, echo Yes
GP_Channels
Multiplayer: On message "pickupArmor"
GP_Channels
Multiplayer: Is host
+ Add action
MP_armor
Pick instance with UID GamePushChannels.MultiplayerEntityUIDForId(GamePushChannels.MultiplayerCustomEventData)
MP_armor
Destroy
ЛегендаMP_playerMP_armorSystemGP_Channels
  • MP_playerОбъект Sprite (Спрайт)
  • MP_armorОбъект Sprite (Спрайт)
  • SystemСистемный объект Construct 3
  • GP_ChannelsПлагин GamePush Channels

echo: Yes нужен на случай, когда подбирающий игрок сам является хостом.

Смерть и возрождение

Каждый игрок авторитетен для своего hp. Когда здоровье закончилось — сообщаем остальным и возрождаемся:

MP_player
Pick instance with UID GamePushChannels.MultiplayerLocalPlayerUID("player")
MP_player
hp0
GP_Channels
Multiplayer: Send "death" with data "" to 0, echo No
MP_player
Set hp to 100
MP_player
Set position to (MP_SpawnPoint.X, MP_SpawnPoint.Y)
GP_Channels
Multiplayer: On message "death"
+ Add action
MP_player
Pick instance with UID GamePushChannels.MultiplayerPlayerProxyUID(GamePushChannels.MultiplayerCustomEventSenderID, "player")
System
Create object DeathFX on layer "game" at (MP_player.X, MP_player.Y)
ЛегендаMP_playerGP_ChannelsMP_SpawnPointSystemDeathFX
  • 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.

Подключение и игроки

ВыражениеВозвращаетПример
MultiplayerMyPlayerIDID текущего игрокаПодпись над своим персонажем
MultiplayerHostPlayerIDID текущего хоста (0, если хост не выбран)Адресат Send message, чтобы написать только хосту
MultiplayerConnectedPlayersCountЧисло подключённых игроков"Игроков: " & GamePushChannels.MultiplayerConnectedPlayersCount
MultiplayerConnectedPlayersAsJSONМассив подключённых игроков как JSON-строкаДля разбора объектом JSON
MultiplayerNetworkPingТекущий пинг в мсИндикатор качества соединения
MultiplayerTickRateТекущий tick rate (20 или 60)
MultiplayerBufferSizeРазмер буфера интерполяции (количество снимков)Отладка
MultiplayerBufferDelayЗадержка буфера интерполяции в мсОтладка
MultiplayerLastTickDeltaДельта последнего тика в мсДвижение с фиксированным шагом внутри On tick

Внутри цикла Each connected player

ВыражениеВозвращает
MultiplayerCurPlayerIDID игрока в цикле
MultiplayerCurPlayerState("key")Поле состояния игрока в цикле
MultiplayerCurPlayerIsHost1, если игрок в цикле — хост, иначе 0
MultiplayerCurPlayerPingПинг игрока в цикле, мс
MultiplayerCurPlayerConnectionStabilityСтабильность соединения 0–1
MultiplayerCurPlayerSessionDurationВремя игрока в комнате, мс

Состояние

ВыражениеВозвращаетПример
MultiplayerMyStateСостояние текущего игрока как JSON-строкаОтладка
MultiplayerMyStateKey("key")Поле собственного состояния. Поддерживает точечные путиMultiplayerMyStateKey("hp")
MultiplayerPlayerState(id, "key")Поле состояния любого игрока по IDMultiplayerPlayerState(2, "hp")
MultiplayerPlayersStateAsJSONКарта состояний всех игроков как JSON-строкаОтладка
MultiplayerGlobalStateAsJSONПолное глобальное состояние как JSON-строкаОтладка

Сообщения (внутри On message)

ВыражениеВозвращает
MultiplayerCustomEventNameИмя последнего сообщения
MultiplayerCustomEventSenderIDID отправителя последнего сообщения
MultiplayerCustomEventDataДанные последнего сообщения

Сущности и прокси

ВыражениеВозвращаетПример
MultiplayerEntityIdnetId текущей сущности (в For each entity / On entity created)
MultiplayerEntityUIDUID экземпляра текущей сущностиС условием 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
MultiplayerProxyPlayerIDID игрока текущего прокси (в On player proxy created/destroyed)
MultiplayerProxyTagТег текущего прокси
MultiplayerProxyUIDUID текущего проксиС условием Pick instance with UID

Оставайтесь на связи

С другими документами раздела вы можете ознакомиться здесь. Для начала работы с GamePush ознакомьтесь с нашими туториалами.

Сообщество GamePush в Telegram: @gs_community.

Для ваших обращений e-mail: official@gamepush.com

Желаем вам успехов!