- PVSM.RU - https://www.pvsm.ru -
Привет.
Статья в помощь разработчикам мультиплеера на UnrealEngine, которые по тем или иным причинам испытывают сложности билда сервера локально (разрабатываете на Mac, или недостаток ресурсов, места, и так далее).
Начнем с проблематики. Хоть движок и мультиплатформенный, сам сервер логично иметь на Linux. Вы можете конечно хостить сервер на Mac, но вряд ли это оправданно. Поэтому, встает резонный вопрос — а как сбилдить сервер под Linux?
Далее проблематика билда сервер под Linux, находясь на другой ОС:
На Linux проблем нет, если есть ресурсы и место (а это минимум 200 гигабайт места и лучше от 8 ядер и 32Гб памяти).
На Windows есть танцы с бубном, но проблема может быть той же, что в п.1
На Mac, это как раз мой случай, я как не пробовал, у меня не получалось, а каждый такой эксперимент разгонял Mac, мешая остальной работе.
Выход? Я решил попробовать сбилдить это дело в облаке. И желательно так дешево, чтобы это можно было делать раз за разом.
AWS вроде предлагает нечто похожее, но только через заявку (не путать с GameLift), и скорее всего встанет в копеечку. Я нашел решение за 50 центов ;)
И о времени. В целом билд такого проекта процесс не быстрый на любом железе. Но все же предупрежу — на выбранном ниже конфиге у меня ушло 5-6 часов от входа на сервер и запуск собранного сервера.
Далее сухое todo для копипаста с некоторыми комментариями. Но поверьте, шишек на черновиках я набил достаточно.
Я выбирал между:
AWS, но за подходящую машинку я бы платил примерно те же 50-70 центов, но за час, если не дороже.
DigitalOcean, примерно в два раза дешевле Амазона, но у них очень неудобный скейл — то ресурсов не хватает, то места. Или докупать тома, что невыгодно.
Внезапно мой выбор пал на Hetzner Cloud. Только на их облачную инфраструктуру, где вы можете запустить сервер также на час. И стоит это всего 0.093 евро. Ну не круто ли?!
Тут не стоит жадничать (вы просто иначе не влезете) и брать сразу этот:
Потому что места вам потребуется примерно 200гб, да и на 8 ядрах работает сильно шустрее. Да-да, я экспериментировал и с предыдущим вариантом.
ОС Ubuntu. И обязательно версию 22.04, это официально поддерживаемая версия Эпиками [1]. Не прочитав требования, я поставил сразу последнюю, билд на финальных нотах не получился, было обидно (ispc.generated-файлы не билдились).
Вам нужно создать пользователя в группе sudo, так как билд под рутом запрещен. Так как сервер у нас сугубо под одну задачу на несколько часов, я не стал париться с какой-либо безопасностью и системой прав, просто создал пользователя builder. Ну и обновить пакеты конечно тоже следует.
apt update && sudo apt upgrade -y
adduser builder
usermod -aG sudo builder
При создании пользователя спросит пароль, он вам в последующем пригодится.
Далее просто переходим под созданного пользователя и прямо там же можем клонировать репозиторий движка нужной версии (напомню, текущая статья про 5.5). Для доступа к клонированию репозитория UE не забудьте, что ваш гитхаб-аккаунт должен быть привязан к аккаунту EpicGames.
su - builder
git clone --branch 5.5 https://github.com/EpicGames/UnrealEngine.git
Займет операция выше примерно полчаса. Далее переходим в директорию движка, выполняем сетап и генерацию, а также удаляем два ненужных серверу плагина, иначе они будут вставлять палки в колеса. На этапе сетапа вас как раз спросит пароль пользователя builder.
cd UnrealEngine/
./Setup.sh
./GenerateProjectFiles.sh
rm -rf ./Engine/Plugins/Fab
rm -rf ./Engine/Plugins/Bridge
Вот мы подошли к самому жирному этапу — билду (примерно 3 часа). Для надежности запустим все через screen, чтобы потом вернуться, если разлогинились (screen -r).
screen -S unreal_build
make
Итак, билд движка закончили, двигаемся дальше. Напомню, мы находимся в директории движка, поэтому поднимаемся выше и клонируем уже свой проект.
cd ../
git clone https://github.com/anton-ds/DedicateTest.git
После клонирования переходим в директорию движка и запускаем команду билда сервера. Это займет еще пару часов, но повторные ребилды сервера будут конечно быстрее.
cd UnrealEngine/
./Engine/Build/BatchFiles/RunUAT.sh BuildCookRun
-project="/home/builder/DedicateTest/DedicateTest.uproject"
-noP4 -platform=Linux -server -build -cook -stage -pak -archive
-archivedirectory="/home/builder/DedicateTest/BuildOutput"
Напомню, builder - наш пользователь, под которым мы билдили, также его одноименная директория, куда мы склонировали проект (в моем случае это DedicateTest). Итоговый результат мы получим в поддиректории BuildOutput нашего проекта.
Я намеренно в статье не упомянул как вообще правильно писать сетевые игры на Unreal Engine (на самом деле это все есть из коробки), так как заголовок предполагает, что вы читаете для конкретной цели – билд сервера, и знаете как все остальное устроено.
Тут следует заметить, что облачный сервер выполнил свою задачу и может быть удален. Вы просто копируете директорию BuildOutput/LinuxServer на свой продакшен сервер и запускаете его уже там. Но разово рекомендую следующие шаги проверить на текущем.
На сервере переходим в директорию нашего игрового сервера и запускаем сервер (сначала открыв порт, по которому сервер будет слушать — в моем случае это 7777). Напомню, мы все еще под пользователем builder и под ним и остаемся. А код проекта — DedicateTest.
sudo ufw allow 7777/udp
sudo ufw reload
cd ./LinuxServer
./DedicateTestServer.sh ThirdPersonMap -port=7777
Обратите также внимание, в параметрах запуска сервера я также передаю название карты, на которой запущен сервер. В моем случае так удобнее.
Ну все, предполагаем, что клиент у вас сбилжен на той же версии, запускаем игру. Возможно, у вас уже реализована логика подключения к серверу, но если нет, то вы можете открыть консоль в самой игре (~) и ввести команду, указав IP сервера и порт.
open <ip>:7777
В логах самого сервера вы должны увидеть успешное подключение по IP вашего клиента. Подключившись еще одним клиентом, вы уже сможете взаимодействовать между клиентами посредством сервера.
Но есть нюанс...
Есть логичное требование — и сервер и клиент должны быть собраны из одной версии кода. Ну вот только Unreal Engine в это вкладывает несколько больше — например, билд из исходников и билд из бинарной версии (той, что вы запускаете из Лаунчера) — разные по версиям билды. (причем ошибку совместимости может давать не всегда)
Самое простое и грамотное решение — это билдить еще и клиент из исходников, и это даже рекомендуется для мультиплеерных игр. Но мы исходили из того, что прямо здесь и сейчас мы этого сделать не можем или не хотим.
Итак, ошибка совместимости выражается в следующем — в момент подключения клиента сервер ругается ошибкой в логах:
LogHandshake: CheckVersion: Incompatible version. bValidHandshakeVersion: 1, bValidNetVersion: 0, GHandshakeEnforceNetworkCLVersion: 0, RemoteMinVersion: 3, RemoteCurVersion: 4, MinSupportedHandshakeVersion: 3, CurrentHandshakeVersion: 4, RemoteNetworkVersion: 2530911350, LocalNetworkVersion: 4263286266, RemoteNetworkFeatures: GenericReplication, LocalNetworkFeatures: GenericReplication
CheckVersion: Incompatible version ... RemoteNetworkVersion: 2530911350, LocalNetworkVersion: 4263286266.
Для чернового фикса, чтобы проверить работу вашего клиента с сервером, можно сделать следующее (важно! такой фикс НЕ для продакшена!). Либо вы можете написать свою логику проверки версий.
В файле Source/DedicateTest/DedicateTest.cpp (название файла зависит от названия вашего проекта) добавляем следующее:
// Copyright Epic Games, Inc. All Rights Reserved.
#include "DedicateTest.h"
#include "Modules/ModuleManager.h"
class FDedicateTestModule : public FDefaultGameModuleImpl
{
public:
virtual void StartupModule() override
{
FNetworkVersion::IsNetworkCompatibleOverride.BindStatic(&FDedicateTestModule::IsNetworkCompatible);
FNetworkVersion::GetLocalNetworkVersionOverride.BindStatic(&FDedicateTestModule::GetLocalNetworkVersion);
}
virtual void ShutdownModule() override
{
FNetworkVersion::IsNetworkCompatibleOverride.Unbind();
FNetworkVersion::GetLocalNetworkVersionOverride.Unbind();
}
static bool IsNetworkCompatible(uint32 LocalNetworkVersion, uint32 RemoteNetworkVersion)
{
// here you can add your own logic for checking network compatibility
return true;
}
static uint32 GetLocalNetworkVersion()
{
// must be equal to the server version
return 4263286266;
}
};
IMPLEMENT_PRIMARY_GAME_MODULE( FDedicateTestModule, DedicateTest, "DedicateTest" );
Вот число 4263286266 это как раз число сетевой версии из логов сервера. Пересобираем клиентскую сборку (не сервер), запускаем. Все должно заработать.
На этом все, не забудьте удалить сервер сборки ;-)
Автор: anton_dolganin
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/server/422039
Ссылки в тексте:
[1] Эпиками: https://dev.epicgames.com/documentation/en-us/unreal-engine/hardware-and-software-specifications-for-unreal-engine
[2] Источник: https://habr.com/ru/articles/916692/?utm_source=habrahabr&utm_medium=rss&utm_campaign=916692
Нажмите здесь для печати.