Local multiplayer test | Godot

Добавил в один из своих прототипов базовую поддержку игры по локальной сети, чтобы иметь возможность тестировать виртуальные локальные сети простым приложением и оценить, насколько сложно делать мультиплеерные проекты в Godot 3x под этот стек технологий.

Local multiplayer test | Godot

Вступление

Для начала зайду немного с другой стороны - эти несколько недель мне случилось присутствовать на сессиях сетевой игры в Master of Orion 2, где играло обычно 5-8 человек, продолжая прерванную в прошлый раз партию, периодически сдавая кого-то из отсутствующих под управление компьютера.

<i>Master of Orion II, один из моментов</i><br />
Master of Orion II, один из моментов

Играли мы через виртуальную опенсурсную сеть zerotier one, в которой один из участников должен зарегистрироваться, чтобы создавать сети, а прочим достаточно скачать лишь приложение и подсоединить его к созданной сети, по её имени. Таким образом все получают виртуальные IP в этой сети и далее мы переходим к игре в Master of Orion, запущенный в DosBox с включенной эмуляцией ipx. В конфиге досбокса один из игроков прописывает, что будет сервером - простая строка ipxnet startserver, а прочим уже нужно прописать в конфиге конкретный виртуальный IP того участника, который стал сервером. То есть им нужно каждому прописать примерно такую строчку: ipxnet connect 192.168.2.100

<i>файл настроек досбокса</i><br />
файл настроек досбокса
<i>пара строчек управляющих ipx соединением - сервер должен убрать решётку с первой строки, клиенты - убрать её со второй строчки и ввести IP этого конкретного сервера, вместо указанного на картинке значения</i><br />
пара строчек управляющих ipx соединением - сервер должен убрать решётку с первой строки, клиенты - убрать её со второй строчки и ввести IP этого конкретного сервера, вместо указанного на картинке значения
<i>открытое окошко состояния приложения zerotier - галочкой отмечена сеть, к которой он сейчас подключен (чтобы её создать нужно зарегистрироваться и создать сеть на отдельной вёб-странице, для подключения к созданной регистрация не нужна)</i><br />
открытое окошко состояния приложения zerotier - галочкой отмечена сеть, к которой он сейчас подключен (чтобы её создать нужно зарегистрироваться и создать сеть на отдельной вёб-странице, для подключения к созданной регистрация не нужна)
<i>если нажать show networks, то пользователь видит свой IP в этой сети (Win 7 поддерживает только старую версию zerotier, в новых интерфейс должен отличаться, но смысл такой же)</i><br />
если нажать show networks, то пользователь видит свой IP в этой сети (Win 7 поддерживает только старую версию zerotier, в новых интерфейс должен отличаться, но смысл такой же)

Далее игрок-сервер запускает уже сам Орион, мультиплеерную игру и все начинают к ней подключаться. Собственно, наблюдая это всё, я подумал, что игру через ipx в том же Godot должно быть не слишком сложно сделать и захотел запрототипировать что-то элементарное. Так как возможность игры по сети - штука занятная, но возится с TCP/IP и выделенными серверами никогда особо не хотелось, поэтому обычно эту область не рассматривал.

Для начала решил немного осмотреться и проверить, какие ещё есть приложения для виртуальной локальной сети. Насколько просто их использовать и соединяться. Через свою новую сеть в zerotier, например, мне так и не удалось соединить досбоксы у себя и на компьютере друга (возможно, это из за совпадения поля адресов с той первой сетью - вроде это единственный оставшийся момент, который я пока не тестировал). После чего я вспомнил про hamachi, но с ним ситуация оказалось какой-то совсем уже печальной в 2к23, по крайней мере я решил с ним не возиться, но при желании использовать можно.

В итоге одним из элементарных вариантов оказался Radmin_VPN - просто каждый скачивает приложение, без регистраций, один участник заводит имя сети с паролем, другой к ней подключается и вводит пароль. Получаем виртуальную сеть и её IP адреса. Профит. Таким образом у меня получилось сконнектить досбоксы и играть в Орион уже с другом. Ну и в прочие lan игры, разумеется, можно. На винде ещё желательно, для порядка, выкинуть radmin из автозагрузки, зайдя в её настройки через msconfig.

<i>лаконичный интерфейс Radmin (хотя там ещё много всего спрятано в настройки) - вверху имя и виртуальное IP пользователя, ниже название созданной сети (master22) с перечнем подключенных клиентов и их адресами (на данный момент клиент не в сети)</i><br />
лаконичный интерфейс Radmin (хотя там ещё много всего спрятано в настройки) - вверху имя и виртуальное IP пользователя, ниже название созданной сети (master22) с перечнем подключенных клиентов и их адресами (на данный момент клиент не в сети)

Сетевой прототип. Чат

Возвращаемся к игровому движку. Я взял один из своих последних прототипов, где относительно мало кода, плюс проглядывается какой-то возможный сетевой потенциал и стал добавлять поддержку локальной сети.

<i>cначала происходит процедура коннекта - один игрок должен просто нажать SERVER, другой вводит IP сервера в поле. Если запускать в два окна, то указанный по умолчанию IP менять не нужно.</i><br />
cначала происходит процедура коннекта - один игрок должен просто нажать SERVER, другой вводит IP сервера в поле. Если запускать в два окна, то указанный по умолчанию IP менять не нужно.

Начал с простого и сперва добавил чат. Уже здесь требуется немного "сломать себе мозги" под сетевое мышление: вот у нас есть один объект, который управляет чатом и которому присвоен сетевой идентификатор, а дальше с ним как та история, про "есть два стула" - что себе возьмёшь, что отправишь по сети.

Таким образом у нас есть один объект в сети, который существует и на сервере и на клиенте - у него сейчас прописаны полномочия управления чатом и получая новое сообщение в чат он должен стереть вводимый текст у текущего игрока, добавить его в видимый тем игроком чат и отослать данный текст своему двойнику на прочих запущенных приложениях, в чат остальным игрокам. Но требуется чётко понимать, что мы отправляем, а что нет. Например, стирание строки ввода мы не отсылаем, так как это уберёт и набираемый прочими игроками текст. А вот добавление строки в свой чат мы и отсылаем и делаем у себя отдельно, так как отосланное нам самим же не вернётся.

<i>чат, запущенный в два окна, сообщения отсылаются из каждого</i><br />
чат, запущенный в два окна, сообщения отсылаются из каждого
<i>частичный код окна чата, которое и является сетевой сущностью - функция _on_LineEdit_text_entered получает введённый пользователем текст, стирает строчку и добавляет запись в чат, в конце вызывая remote func описанную ниже (которая добавит запись прочим)</i><br />
частичный код окна чата, которое и является сетевой сущностью - функция _on_LineEdit_text_entered получает введённый пользователем текст, стирает строчку и добавляет запись в чат, в конце вызывая remote func описанную ниже (которая добавит запись прочим)

В целом с менеджером чата понятная история - это один узел, в нём нет циклов, он откликается именно на события ввода от любого игрока. Уже можно делать игры, основывающиеся на таком чате или походовом обмене информацией. Собственно - тот же Master of Orion это базово такая же большая чат-система, игрок в свой ход совершает различные манипуляции, как бы формируя пакет сообщений. На следующем ходу все эти пакеты будут собраны, проанализированы и применены - будут заключены альянсы, корабли долетят в нужные места и вступят/не вступят в схватки, построятся все здания, прибавится прогресса в технологиях, спишутся/добавятся средства по договорам и так далее.

Сетевой прототип. Сущности

Что касается нескольких игроков, или нескольких отдельных сетевых сущностей, то здесь дело несколько осложняется. С одной стороны можно обходиться всё тем же единым объектом, который будет всё обрабатывать, с другой стороны нам так и так придётся в каждом клиенте заводить хотя бы визуализации всех персонажей игроков.

В различных гайдах как раз обычно рекомендуют сделать каждого персонажа отдельной сетевой сущностью, которая будет что-то делать сама (допустим, двигаться) и отсылать всем своим прочим сетевым копиям что-то (например, свои текущие координаты). Каждая сущность при этом обычно делается отдельным полноценным префабом и создаётся на уровне через код. Ну и камера там обычно висит не на персонажах, а отдельно.

В моём проекте da~Mage к герою уже прикреплена камера, он пока не является префабом и много прочего сопутствующего кода, поэтому переделать его под сетевую сущность не так просто. Придётся, например, откреплять камеру и либо цеплять её через код к нужной модели, либо внутри моделей включать камеру только на той, которую контролирует данный PC. Одним словом нужно принять множество решений о том, как именно распараллелить задачи - делать выбор цели колладером камеры на сервере, или в клиенте. Врагов, видимо, стоит считать на сервере и отправлять их положение в клиенты. И так далее.

Вместо этого я пока создал на уровне пару моделей попроще, которые можно двигать стрелками - вот они уже являются двумя сетевыми сущностями. Вместо того чтобы создавать их через код в момент запуска и крепить к заготовленным пустышкам - я пока просто прописал условия, которые определяют кто из игроков будет контролировать каждую из моделей: одну двигает сервер, другую клиент.

Local multiplayer test | Godot
<i>управляемые модели находятся на подписанных позициях server avatar и client avatar, также у них у каждой над головой мелкая надпись user 0 и usеr 1</i><br />
управляемые модели находятся на подписанных позициях server avatar и client avatar, также у них у каждой над головой мелкая надпись user 0 и usеr 1

Таким образом контролирующий модель игрок сможет её двигать, а другому игроку она будет отсылать свои координаты и "перепрыгивать" в них. Основной же герой, который имеет камеру, анимации и бегает по уровню WASD кнопками - для каждого игрока независимый и отвязан от сети, то есть его просто не видно в окне на другом PC.

<i>внутри моделей описано дополнительное условие, чтобы ими управлял только один игрок, а не оба - это можно делать иначе, анализируя сетевой id, но пока сделал так</i><br />
внутри моделей описано дополнительное условие, чтобы ими управлял только один игрок, а не оба - это можно делать иначе, анализируя сетевой id, но пока сделал так

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

Таким образом мы приходим к тому, что в 3д сетевой игре на каждом клиенте у нас скорей всего будет как минимум одна сетевая сущность-менеджер, и по одной сетевой сущности для каждого персонажа.

Итоговый тестовый билд

В итоге я выложил windows и linux билды на страницу проекта da~Mage:

Вёб-версия работает как обычно, в ней нет сетевых экспериментов. А внутри тестовых билдов появляется переключатель с сингла на Multiplayer.

Для теста сетевой игры в два окна на одном компьютере нужно в одном окне нажать SERVER, а в другом Client join, не трогая предустановленный IP - 127.0.0.1

Для теста сетевой на разных компьютерах нужно, чтобы они были в одной локальной сети или же сделать виртуальную локальную сеть между ними через приложения о которых я уже писал выше - radmin_vpn, zerotier и так далее.

Когда компьютеры в локальной сети, то один запускает игру у себя и жмёт SERVER, а другой вводит IP компьютера ставшего сервером и тогда уже нажимает Client join. Если чат появился, то соединение установлено. Теперь, если нажать на кнопку Старт, оба игрока появятся на локации и не будут видеть самих себя, однако смогут управлять одной из двух болванок персонажей на уровне СТРЕЛКАМИ (не WASD) - те упираются в препятствия и не сваливаются в пропасть.

Собственно, приложение позволяет протестировать - работает ли установленная локальная сеть и пойдёт ли в ней большая часть существующих игр с ipx lan мультиплеером.

1212
3 комментария

А почему третий годо, если не секрет?

1

А почему нет?

1