Devlog #11: Мультиплеер
Привет всем! Это 11-й девлог для CaveVox. На этот раз я расскажу о многопользовательских аспектах игры. Также считаю, что всё ещё иду по графику, чтобы завершить все основные функции для раннего доступа, который запланирован на середину февраля.
До этого выйдет девлог 12, где я поделюсь дополнительными подробностями. После раннего доступа в марте запланировано крупное обновление.
Я также рад сообщить, что CaveVox примет участие в Medieval Fest 2026, который пройдёт с 20 по 27 апреля!
Мультиплеер
После завершения основных фундаментальных частей игры я перешёл к реализации многопользовательского режима, что заняло около недели сосредоточенной работы.
Как вы знаете, я использую Godot, который предоставляет несколько уровней сетевой функциональности:
- Низкоуровневый API (ENet / PacketPeer / StreamPeer) — полный контроль над протоколом и логикой;
- Высокоуровневый Multiplayer API — репликация, авторитет, владение;
- RPC — вызовы функций между клиентами и сервером;
- MultiplayerSynchronizer — автоматическая синхронизация состояния узлов.
Однако я пошёл другим путём: стандартный сетевой стек Godot оказался слишком ограниченным для CaveVox, и поскольку я активно использую Rust, я построил мост между движком и отдельным сервером, используя Quinn.
Что такое Quinn?
Quinn — это компактная библиотека для протокола QUIC — современного транспортного уровня поверх UDP, который объединяет надёжность в стиле TCP, мультиплексирование потоков, встроенное шифрование и низкую задержку установления соединения.
QUIC позволяет:
- использовать UDP без его традиционных ограничений;
- иметь несколько независимых потоков внутри одного соединения без блокировки по принципу head-of-line;
- отправлять как надёжные, так и ненадёжные сообщения;
- устанавливать соединения быстрее по сравнению с TCP + TLS;
- управлять отдельными каналами для разных типов трафика (ввод игрока, события, снапшоты, чат).
Короче говоря, QUIC — это современный гибрид лучших возможностей TCP и UDP, разработанный для realtime-приложений и сетевых игр.
Для FPS-рогалика это критично: высокая частота обновлений, предсказуемая задержка, независимые каналы для важных и второстепенных сообщений и полный контроль над серверной логикой.
Кооператив
Поскольку игра планируется как кооператив на четырёх игроков, я спроектировал сервер в первую очередь как ретранслятор. Входящие сообщения от клиентов просто пересылаются другим участникам сессии без тяжёлой симуляции на стороне сервера.
Это называется relay-архитектура: сервер действует как центральный узел маршрутизации, обеспечивая доставку пакетов и порядок сообщений там, где это нужно, и синхронизируя клиентов, не беря на себя полную игровую логику.
Это снижает нагрузку на сервер, упрощает масштабирование и сохраняет минимальную задержку — что критично для кооперативных FPS-игр, где важны отзывчивость и точность.
Например, если клиент A гасит факел, сервер просто пересылает событие всем остальным — и у них факелы тоже гаснут. Сервер не имеет авторитета или валидации, поскольку в небольшом кооперативе из четырёх игроков в этом нет необходимости — операции доставляются максимально быстро.
Также для мультиплеера требуется клиент Steam, так как игра привязана к Steam для получения никнеймов игроков. Без него игрок не появится в лобби. Я также добавил отображение никнеймов над персонажами и со временем планирую добавить больше удобных функций.
Датаграммы
Некоторые операции — такие как движение игрока, анимации и повороты — передаются через датаграммы.
Датаграммы — это небольшие пакеты без гарантированной доставки и порядка, отправляемые с высокой частотой. Они могут теряться по пути, но постоянные обновления состояния в последующих пакетах сохраняют синхронизацию: позиция и ориентация просто корректируются свежими данными.
Этот метод идеально подходит для данных в реальном времени, где своевременность важнее стопроцентной надёжности.
Двунаправленные потоки
Все критически важные операции — такие как подключение игроков, подтверждение действий, урон, смерти или активация объектов — отправляются по отдельным надёжным каналам с гарантированной доставкой и сохранением порядка.
В QUIC это реализовано через двунаправленные потоки: независимые двусторонние потоки внутри одного соединения, которые не блокируют друг друга, изолируя разные типы трафика. Потеря или задержка в одном потоке не влияет на другие — идеально для игр.
Используя эту систему, я реализовал:
- полноценное лобби игроков;
- общий мир через единое зерно генерации;
- синхронизацию позиций;
- синхронизацию взаимодействий с объектами.
Это особенно эффективно, потому что клиенты детерминированно генерируют идентичные миры. В результате по сети передаётся только минимальный объём данных — события и корректировки — что делает сервер лёгким и простым.
Другие изменения
- Обновлена генерация деревьев с использованием кэшей и потоков для ускорения;
- Добавлены новые типы деревьев — ель и дуб на поверхности (скриншот);
- Исправлено отображение названия уровня поверхности при входе/выходе из подземелий;
- Добавлена очередь рендера на основе позиции игрока — сначала отрисовываются области рядом с игроком;
- Добавлена выгрузка чанков в зависимости от уровня игрока — рендерятся только ближайшие 3 уровня, дальние чанки выгружаются;
- Оптимизирована загрузка ресурсов при запуске игры с использованием потоков;
- Оптимизированы потоки чанков для уменьшения блокировок, что значительно ускорило рендеринг;
- Добавлены все базовые анимации игрока (ходьба в четырёх направлениях, падение, прыжок), интегрированные в игровую логику;
- Многочисленные исправления в игровом меню, запуске игры и фоновых процессах (раньше некоторые алгоритмы продолжали работать в фоне);
- Исправлена окклюзия звука — теперь она привязана к активному игроку;
- Завершены все статические части поверхности над подземельем (пока без NPC или логики, это будет добавлено в следующем обновлении).
Заключение
Впереди ещё много работы над мультиплеером и основными механиками игрока. Надеюсь, этот девлог был информативным — спасибо за чтение!