Игры (GameDev)

Divo RP

Клиент-серверная многопользовательская ролевая игра по подобию GTA SA RP с открытым городским миром на Unity. Игроки подключаются к общему персистентному серверу, создают и развивают персонажа, перемещаются по городу пешком и на транспорте, взаимодействуют в реальном времени через общий чат, участвуют в экономике (банк, кредиты, недвижимость, работа) и боевой системе. Весь игровой стейт хранится между сессиями: выйдя из игры и вернувшись, игрок оказывается там же, с тем же балансом, инвентарем и состоянием персонажа.
Unity C# FishNet

Задача

Требовалось построить с нуля технический фундамент сетевой ролевой игры, где десятки игроков одновременно находятся в одном мире и видят действия друг друга в реальном времени. Это не игра на двоих по локальной сети, а полноценная архитектура с тремя нетривиальными требованиями, которые обычно и определяют успех или провал подобных проектов:
  1. Синхронизация состояния в реальном времени между всеми клиентами - движение игроков, физика транспорта, стрельба, поведение NPC - при минимальной нагрузке на канал.
  2. Защита от недобросовестных клиентов. В экономической игре клиенту нельзя доверять: любая логика начисления денег, проверки баланса, нанесения урона должна жить на сервере и быть невозможной к подделке со стороны игрока.
  3. Персистентность мира. Прогресс сотен игроков - деньги, недвижимость, кредиты, позиция, оружие, состояние здоровья - должен надежно сохраняться в базе данных и переживать перезапуск как клиента, так и сервера.
Поверх этого фундамента нужно было реализовать обширный геймплей: транспорт с реалистичной физикой и передачей управления по сети, боевую систему с хитбоксами и рэгдоллами, ИИ городских NPC, глубокую экономику (банковские вклады, три типа кредитов, страховки, аренда и покупка жилья, автошкола с экзаменом), навигацию по карте и мультиязычный интерфейс.

Решение

В основу положена сетевая модель FishNet с четким разделением ответственности через три типа удаленных вызовов:
  • ServerRpc - клиент просит сервер выполнить действие (купить топливо, нанести урон, открыть вклад);
  • ObserversRpc - сервер рассылает результат всем наблюдателям (визуальные эффекты, спавн объектов, синхронизация);
  • TargetRpc - сервер отвечает конкретному клиенту-инициатору (обновить его баланс, открыть окно).
Каждая экономическая операция построена по единому защищенному контракту: клиент инициирует запрос, сервер загружает актуальные данные пользователя из БД, проверяет условия (достаточно ли средств, корректны ли границы суммы), атомарно изменяет состояние в базе, и только потом возвращает результат. Подделать баланс на стороне клиента физически невозможно - клиент вообще не является источником истины.
Персистентность реализована через тонкий собственный слой доступа к MS SQL Server с обобщенным маппером на рефлексии (Select<T>), который автоматически проецирует строки результата на типизированные C#-модели без ручного кода для каждой сущности. Записи в БД выполняются асинхронно, не блокируя игровой поток, а фоновая задача автосохранения фиксирует позицию и инвентарь игрока каждые 10 секунд.

Архитектура и сложности

1. Серверно-авторитарная экономика. Все денежные операции - заправка, питание, покупка/аренда квартир, банковские вклады, кредиты с первоначальным взносом и графиком платежей, страховки, оплата автошколы - реализованы как серверные транзакции с валидацией бизнес-правил (минимальные и максимальные суммы вклада, размер первого взноса 25%, порог сдачи экзамена). Клиент получает только итоговое разрешенное состояние. Это полностью исключает класс уязвимостей «накрутка денег с клиента».
2. Передача сетевого владения транспортом - самая сложная распределенная задача проекта. В отличие от игрока, автомобиль не имеет постоянного владельца: пока он стоит, им управляет сервер; как только игрок садится за руль, владение объектом динамически передается этому клиенту (GiveOwnership), чтобы физика управлялась локально без сетевой задержки. При выходе из машины владение снимается и возвращается серверу. Для всех остальных игроков положение чужой машины сглаживается интерполяцией (Lerp/Slerp позиции и поворота), чтобы движение выглядело плавным несмотря на дискретные сетевые апдейты. Корректная обработка входа/выхода, репарентинга игрока к машине, переключения камер и мини-карты, остановки автомобиля при выходе - десятки граничных случаев, каждый из которых при ошибке ломает сессию.
3. Боевая система с авторитарным хит-реджистром. Выстрел проходит проверку на сервере: рейкаст определяет попадание, урон масштабируется по хитбоксу (попадание в голову - летально, в корпус - повышенный урон), после чего сервер пересчитывает броню и здоровье цели, пишет результат в БД и рассылает наблюдателям визуальные эффекты - кровь, трассеры пуль, активацию рэгдолла с импульсом отталкивания в направлении выстрела. Здоровье и броня - серверная истина, клиент не может не умереть.
4. ИИ NPC как серверный конечный автомат. Поведение городских персонажей (патрулирование, испуг, бегство со сменой направления при столкновении, агрессия и преследование игрока, получение урона, смерть с рэгдоллом) исполняется только на сервере и реплицируется клиентам - что исключает рассинхрон поведения между игроками.
5. Сопутствующие подсистемы. Аутентификация и регистрация с хешированием паролей HMAC-SHA512 с персональной солью на каждый аккаунт; собственная система локализации (ru/en) с ленивой регистрацией ключей; навигация с преобразованием координат игрового мира в пространство мини-карты и полноэкранной карты, GPS-маршрутизация; интерфейс на Unity UI Toolkit (UXML/USS); загрузка ассетов и префабов в рантайме через Addressables; ролевой чат с раздельными каналами (локация, сервер, фракция). Отдельный режим выделенного сервера (UNITY_SERVER) с автоматическим спавном мира и подробным журналированием процесса инициализации для диагностики.

Результат

  • Реализована законченная сетевая архитектура уровня MMO: серверно-авторитарная модель, персистентный мир на SQL, real-time-синхронизация - фундамент, на котором проект может масштабироваться по контенту без переписывания ядра.
  • 15+ взаимосвязанных игровых систем доведены до рабочего состояния: экономика, банкинг, кредитование, недвижимость, транспорт, бой, ИИ, автошкола с экзаменом, навигация, чат, локализация, аутентификация.
  • Защищенная экономика: 100% денежных и боевых операций валидируются на сервере - архитектурно закрыт целый класс читерских атак, фатальных для онлайн-проектов с внутриигровой экономикой.
  • Решена ключевая инженерная задача динамической передачи сетевого владения транспортом со сглаживанием - то, на чем спотыкается большинство любительских сетевых проектов.
  • Надежная персистентность: автосохранение прогресса каждые 10 секунд и неблокирующая запись в БД, что гарантирует сохранность мира при сбоях и перезапусках.
  • ~4 600 строк собственного прикладного кода в 54 модулях (без учета сторонних библиотек), организованных по доменным областям (Network, Player, Car, City, DB, NPC, UI) - структура, в которой новые функции добавляются изолированно, не задевая ядро.

Стек

Движок и язык: Unity 2023.2 (C#, .NET).
Сеть: FishNet (server-authoritative, ServerRpc / ObserversRpc / TargetRpc, SyncVar/SyncList, динамическая передача владения объектами, выделенный сервер).
База данных: Microsoft SQL Server - собственный слой доступа с обобщенным маппером на рефлексии, асинхронные транзакции.
Интерфейс: Unity UI Toolkit (UXML/USS), TextMesh Pro.
Графика и контент: Addressable Assets (динамическая загрузка), Cinemachine (камеры), система рэгдоллов и Animation Rigging, постобработка, система трафика, мини-карта и навигация.
Безопасность: HMAC-SHA512 с персональной солью для хранения паролей, серверная валидация всех игровых операций.
Прочее: Newtonsoft.Json (сериализация инвентаря и моделей), собственная система локализации (ru/en). 
Сюда Туда