Important
В проекте используется .NET 8.
Перед тем как начать разработку, ознакомься с Wiki.
Note
Чтобы в Godot настроить интеграцию с Rider, необходимо зайти в Editor -> Editor Settings -> Dotnet -> Editor. В списке External Editor выбрать JetBrains Rider и очистить значение Custom Exec Path Args.
Note
Для более быстрого дебага игру можно запускать с различными параметрами командной строки.
--server
сразу запускает игровой сервер.
--auto-connect-ip 127.0.0.1
запускает клиент и автоматически подключается к серверу по указанному адресу (в данном случае 127.0.0.1).
--auto-connect-port 25566
запускает клиент и автоматически подключается к серверу по указанному адресу и указанному порту (в данном случае 25566). Работает только вместе с --auto-connect-ip
.
Для быстрого и удобного тестирования рекомендуется настроить в Rider следующие конфигурации запуска:
- Тип:
.Net Executable
. Название:Server
. Program Arguments:--server
. - Тип:
.Net Executable
. Название:Autoconnect (1)
. Program Arguments:--auto-connect-ip 127.0.0.1
. - Тип:
.Net Executable
. Название:Autoconnect (2)
. Program Arguments:--auto-connect-ip 127.0.0.1
. - Тип:
Multi-Launch
. Название:Fast-test (1 client)
. Tasks:Server, Autoconnect (1)
. - Тип:
Multi-Launch
. Название:Fast-test (2 clients)
. Tasks:Server, Autoconnect (1), Autoconnect (2)
.
Проект разделен на несколько модулей, каждый из которых отвечает за отдельную сцену или функциональность.
- Scenes: Содержит игровые сцены и их обработчики
Root
: Самая верхнеуровневая сцена. Вызывает инициализцию других систем, содержит в себе сцену Game или MainMenu, а также ссылку на PackedScenesContainer.Game
: Сцена с игрой (не меню). Отвечает за инициализацию сети, подключение, управление общеигровым состоянием, содержит в себе сцену SafeWorld или BattleWorld.PackedScenesContainer
: Контейнер, который содержит ссылки на все прототипы сцен в игре (тип PackedScene).Screen
: Содержит набор сцен с интерфейсом пользователя (HUD, меню, экран загрузки, консоль сервера).World
: Содержит верхнеуровневые сцены SafeWorld и BattleWorld, а также все игровые объекты и их логику.
- Scripts: Содержит вспомогательный код, не содержит сцены (tscn файлы)
Content
: Содержит контейнеры со ссылками на ресурсы игры (музыка, звуки, текстуры, частицы)KludgeBox
: Библиотека с наработками из других проектов (шина событий, перехват сетевых пакетов, логеры, таймеры и т.п.)Utils
: Вспомогательные классы (обработка ошибок, работа с аргументами командной строки) и код вспомогательных нод, без tscn файлов (нода с системой пинга, нода-таймер)
Сцены и обработчики хранятся в одной папке. Например, в папке ClientRoot
хранится ClientRoot.tscn
(сцена) и ClientRoot.cs
(обработчик).
Обработчики могут быть разбиты на несколько partial
классов по функционалу. Например, класс ClientRoot
разбит на файлы ClientRoot.cs
, ClientRootSceneContainer.cs
, ClientRootSingleton.cs
.
Сцены и обработчики для клиента и сервера хранятся в соседних папках. Например:
- Root: Общая папка со всеми файлами связанными со сценой Root
- ClientRoot: Папка с файлами сцены
Root
для клиента.ClientRoot.tscn
ClientRoot.cs
ClientRootSceneContainer.cs
ClientRootSingleton.cs
- ServerRoot: Папка с файлами сцены
Root
для сервера.ServerRoot.tscn
ServerRoot.cs
ServerRootSceneContainer.cs
ServerRootSingleton.cs
RootService.cs
: Статичный класс с общими функциями, которые используются и на клиенте и на сервере.
- ClientRoot: Папка с файлами сцены
Сетевые пакеты объявляются в partial
классе в файле с суффиксом Packets
в том же классе, где они обрабатываются.
Например, есть пакеты, которые обрабатываются в классе ClientGame
, обработчики описаны в файле ClientGameNetworkListener.cs
. В файле ClientGamePackets.cs
описан класс ClientGame
, в котором находятся вложенные классы пакетов.
Root/StarterScene
- Является точкой входа и определяет, будет ли запускаться
ClientRoot
илиServerRoot
сцена.
- Является точкой входа и определяет, будет ли запускаться
ClientRoot
/ServerRoot
- Вызывает инициализацию других систем в
Init()
и запускает игру вStart()
. - Является контейнером для сцен
MainMenuMainScene
иClientGame
/ServerGame
.
- Вызывает инициализацию других систем в
ClientGame
/ServerGame
- Инициализирует сеть и осуществляет подключение.
- Является контейнером для сцен типа
World
.
- Завершение работы клиента
- Завершение работы клиента осуществляется при помощи вызова функции
ClientRoot#Shutdown()
. - При любом способе уничтожения сцены
ClientGame
(включая завершение игры), автоматически будет вызванClientGame#ServerShutdowner
. И если данный клиент является хостом (запускал серверный процесс), то будет вызвана функцияOS.Kill()
для завершения работы сервера.
- Завершение работы клиента осуществляется при помощи вызова функции
- Завершение работы сервера
- Завершение работы сервера осуществляется при помощи вызова функции
ServerRoot#Shutdown()
. - Дополнительно на сервере каждые несколько секунд запускается проверка в
ServerGame#ClientDeadChecker
. И если в ОС не будет найден процесс клиента игры, который запустил данный сервер, то сервер автоматически завершит свою работу.
- Завершение работы сервера осуществляется при помощи вызова функции
- Root: Общая папка со всеми файлами связанными со сценой
Root
- ClientRoot: Папка с файлами сцены
Root
для клиента.ClientRoot.tscn
: Техническая сцена без игровых объектов.ClientRoot.cs
: Имеет ссылки наPackedScenesContainer
(клиентская версия),WorldEnvironment
и настройки игрока. При запуске инициализирует все необходимые сервисы, анализирует параметры командной строки и запускает игру.ClientRootSceneContainer.cs
: Отвечает за смену меню (MainMenuMainScene
) на игру (ClientGame
) и обратно.ClientRootSingleton.cs
: Реализация паттерна singleton для доступа к классуClientRoot
из любой точки проекта.
- ServerRoot: Папка с файлами сцены
Root
для сервера.ServerRoot.tscn
: Техническая сцена без игровых объектов.ServerRoot.cs
: Имеет ссылки наPackedScenesContainer
(серверная версия),Console
. При запуске инициализирует все необходимые сервисы, анализирует параметры командной строки и запускает сервер.ServerRootSceneContainer.cs
: Отвечает за создание дочерней сцены (ServerGame
).ServerRootSingleton.cs
: Реализация паттерна singleton для доступа к классуServerRoot
из любой точки проекта.
- StarterScene: Папка с файлами сцены
StarterScene
. Общая для клиента и сервера.StarterScene.tscn
: Техническая сцена без игровых объектов. Сцена выбрана в качестве стартовой сцены в Godot.StarterScene.cs
: Имеет ссылки на прототипы сценClientRoot
иServerRoot
. В зависимости от параметров командной строки заменяет загруженнуюStarterScene.tscn
наClientRoot.tscn
илиServerRoot.tscn
.
RootService.cs
: Статичный класс с общими функциями, которые используются и на клиенте и на сервере. Отвечает за инициализацию сервисов использующихся и на клиенте и на сервере.
- ClientRoot: Папка с файлами сцены
- Game: Общая папка со всеми файлами связанными со сценой
Game
- ClientGame: Папка с файлами сцены
Game
для клиента.ClientGame.cs
: Запускает функции инициализации из другихpartial
классовClientGame
.ClientGameSceneContainer.cs
: Отвечает за переключение междуBattleWorldMainScene
иSafeWorldMainScene
.ClientGameBaseNetwork.cs
: Отвечает за инициализацию сети и подключение к серверу.ClientGameNetworkListener.cs
: Отвечает за обработку сетевых пакетов с сообщениями верхнего уровня (начало игры, смена мира и т.п.).ClientGamePackets.cs
: Место хранения всех сетевых пакетов, которые обрабатываются в классеClientGame
.ClientGameLoadingScreen.cs
: Предоставляет возможность отображения загрузочного экрана.ClientGameServerShutdowner.cs
: Отвечает за добавление к сценеClientGame
сценыProcessShutdowner
, которая завершает работу сервера при уничтожении сценыClientGame
.- MainScenes: Папка с файлами сцен типа
WorldMainScene
для клиента. Такая сцена объединяет в себе сценыWorld
иHud
.IWorldMainScene.cs
: Общий интерфейс для всех сцен типаWorldMainScene
- BattleWorld: Папка с файлами сцены типа
WorldMainScene
для боевого мира.BattleWorldMainScene.tscn
: Техническая сцена без игровых объектов. Содержит сценыBattleWorld
иBattleHud
.BattleWorldMainScene.cs
: Просто контейнер со ссылками наBattleWorld
иBattleHud
.
- SafeWorld: Папка с файлами сцены типа
WorldMainScene
для безопасного мира.SafeWorldMainScene.tscn
: Техническая сцена без игровых объектов. Содержит сценыSafeWorld
иSafeHud
.SafeWorldMainScene.cs
: Просто контейнер со ссылками наSafeWorld
иSafeHud
.
- ServerGame: Папка с файлами сцены
Game
для сервера.ServerGame.cs
: Запускает функции инициализации из другихpartial
классовServerGame
.ServerGameSceneContainer.cs
: Отвечает за переключение междуServerBattleWorld
иServerSafeWorld
.ServerGameBaseNetwork.cs
: Отвечает за инициализацию сети.ServerGameNetworkListener.cs
: Отвечает за обработку сетевых пакетов с сообщениями верхнего уровня (игрок подключен, игрок отключен, игрок хочет сменить мир и т.п.).ServerGamePackets.cs
: Место хранения всех сетевых пакетов, которые обрабатываются в классеServerGame
.ServerGameServerShutdowner.cs
: Отвечает за добавление к сценеServerGame
сценыProcessDeadChecker
, которая завершает работу сервера, если в ОС будет отсутствовать запущенный игровой клиент.ServerGamePlayerProfiles.cs
: Контейнер с информацией об игроках. Содержит мапу с классамиServerPlayerProfile
.- PlayerProfiles: Папка с информацией об игроках. В отличие от
ServerPlayer
не является сценой и не удаляется вместе сServerWorld
при переключении миров.ServerPlayerProfile.cs
: Класс с информацией об игроке (id, ник, уровень, характеристики и т.п.).
- ClientGame: Папка с файлами сцены
- PackedScenesContainer:
- ClientPackedScenesContainer:
ClientPackedScenesContainer.tscn
: Техническая сцена без игровых объектов. Необходима, чтобы в редакторе Godot настраивать ссылки на прототипы других сцен клиента.ClientPackedScenesContainer.cs
: Содержит ссылки на прототипы других сцен клиента. Получение прототипа любой сцены (для последующего создания сцены), должно начинаться отсюда.
- ServerPackedScenesContainer:
ServerPackedScenesContainer.tscn
: Техническая сцена без игровых объектов. Необходима, чтобы в редакторе Godot настраивать ссылки на прототипы других сцен сервера.ServerPackedScenesContainer.cs
: Содержит ссылки на прототипы других сцен сервера. Получение прототипа любой сцены (для последующего создания сцены), должно начинаться отсюда.
- ClientPackedScenesContainer:
Все сетевые пакеты имеют аннотацию [GamePacket]
.
Все сетевые пакеты имеют суффикс Packet
и префикс SC_
или CS_
. Префикс означает направление передачи (server->client или client->server). Пример наименования: CS_PlayerMovementPacket
.
Стараемся наследовать сетевые пакеты от BinaryPacket
. Сериализацию JSON используем только в крайних случаях (например, для вложенных коллекций кастомных классов). В идеале переделываем структуру пакета так, чтобы получилось избежать использования сериализации в JSON.
Стараемся объединить больше данных в один сетевой пакет (например, разом передать координаты нескольких юнитов).
Все сетевые обработчики имеют аннотацию [EventListener]
. Всегда указываем на какой стороне мы обрабатываем пакет (например, ListenerSide.Client
).
Все сетевые обработчики начинаются с префикса On
и повторяют название пакета без префикса SC_
или CS_
.
В название переменной сетевого пакета также убираем префикс SC_
или CS_
. Пример наименования: OnChangeWorldPacket(SC_ChangeWorldPacket changeWorldPacket)
.
Стараемся использовать резолверы сетевых пакетов. В ClientGame
и ServerGame
заданы дефолтные резолверы: Network.SetDefaultResolver(nid => World.NetworkEntityManager.GetNode((long) nid));
.
Можно делать свои кастомные резолверы. Например, в ClientGame
задан резолвер: Network.AddInstanceResolver(typeof(ClientGame), id => this);
Используем ванильную версию Godot. Время хранится в double
, а все координаты и углы в float
.
Для большинства некритичных вещей (например, визуал и вспомогательные функции) используем float
, и при расчетах просто кастим deltaTime из double
к float
. Для критичных вещей (например, характеристики юнитов) используем double
.