Создаем реальный индикатор кислорода из Subnautica: часть 1

Создаем реальный индикатор кислорода из Subnautica: часть 1

Прокомментировать Просмотры: 3

Если задуматься, то игр, чье действие разворачивается преимущественно в водной среде, не так уж много. Я погружался в эстетику подводного города Восторг в BioShock, боролся за выживание в Barotrauma и изучал безмятежные океаны ABZÛ. Но ни один из этих проектов не вызывал у меня такого спектра эмоций, как Subnautica. Это тот редкий случай, когда планируешь «заскочить на часок», а обнаруживаешь, что за окном глубокая ночь.

Сейчас в раннем доступе появилась вторая часть, и для меня это стало отличным поводом вернуться к оригиналу. При погружении единственным по-настоящему важным индикатором становится уровень кислорода. Он — ваш главный советчик: стоит ли плыть дальше или пора спешно возвращаться на поверхность. Синтетический голос, монотонно произносящий «oxygen», звучит как приговор, когда времени на раздумья уже не осталось. Именно тогда меня посетила мысль: было бы здорово перенести этот счетчик из виртуальности в физический мир. Так родился этот любопытный DIY-проект.

Создаем реальный индикатор кислорода из Subnautica: часть 1
Консоль управления при старте игры

Мир Subnautica — это планета, поглощенная бесконечным океаном. Атмосфера пригодна для дыхания, но основная часть жизни скрыта под толщей воды. После крушения корабля «Аврора» главный герой оказывается в спасательной капсуле посреди пучины. Единственный шанс выжить — адаптироваться к чужеродной среде и научиться использовать доступные ресурсы.

Именно тогда жизненно важным спутником становится счетчик кислорода. Он превращается в вашего главного друга, арбитра и палача. На нем отображаются две ключевые цифры: текущий запас воздуха и максимально возможный в данных условиях.

Тот самый счетчик
Тот самый счетчик кислорода

Пока у героя нет специализированного снаряжения, запаса хватает лишь на пару десятков секунд. По мере прогресса этот лимит растет, что мгновенно отражается на индикаторе.

Задача проста: считывать эти значения в реальном времени и выводить их на внешний девайс. Алгоритм действий таков: получение данных из игрового процесса, передача их на микроконтроллер и отрисовка интерфейса. Самый сложный этап — первый, так как всё зависит от особенностей игрового движка.

Первый взгляд

Стало очевидно: Subnautica — идеальная площадка для экспериментов. Разработчики из Unknown Worlds Entertainment проявили завидную лояльность к моддинг-сообществу. Для игры уже существуют удобные инструменты, такие как фреймворк Nautilus и загрузчик BepInEx. Их я и решил использовать.

Альтернативные методы, вроде прямого чтения памяти (привет, ArtMoney) или захвата экрана с распознаванием образов, показались мне слишком ненадежными: любой апдейт игры мог бы «сломать» всю систему. Для внешнего дисплея я выбрал круглый экран GC9A01 — это идеальный выбор для аутентичного вида.

Модуль GC9A01. Источник
Модуль GC9A01. Источник

Это компактный дисплей с разрешением 240×240 точек, работающий по SPI. В качестве «мозга» я выбрал ESP32 — доступный и функциональный контроллер. Данные планирую отправлять через UDP-широковещательные пакеты, чтобы избежать привязки к конкретному IP-адресу.

Извлечение данных

Чтобы получать доступ к игровым переменным, я написал небольшой плагин на C#. Суть проста: каждые 200 мс опрашивать объект менеджера кислорода:

float oxygen = Player.main.oxygenMgr.GetOxygenAvailable();
float capacity = Player.main.oxygenMgr.GetOxygenCapacity();

Перед началом работы я убедился, что установлена актуальная версия игры, и настроил BepInEx. Для активации консоли в файле конфигурации BepInEx.cfg я изменил параметр [Logging.Console] на true.

Окружение для разработки

Для компиляции плагина под Unity 2019.4 потребовался .NET SDK. Мой плагин представляет собой библиотеку классов, которая подгружается в процесс игры при старте. BepInEx автоматически сканирует папку plugins и берет на себя всю работу по интеграции.

Написание кода

Я создал проект OxygenTap.csproj и подключил необходимые библиотеки. Важным моментом стало добавление ссылок на UnityEngine и Assembly-CSharp, чтобы компилятор «видел» игровые объекты. Сам код плагина довольно лаконичен: он использует таймер для периодической отправки данных и выполняет проверку Player.main != null, чтобы избежать ошибок при загрузке главного меню.

Данные от самодельного плагина в консоли
Данные, поступающие в консоль через самописный плагин

Отправка

Для передачи данных я отказался от громоздкого JSON в пользу простого строкового формата с разделителем: O2;123.0;135.0. Это минимизирует накладные расходы и позволяет парсить сообщения без лишних аллокаций памяти. Префикс O2 защищает от «мусора» и дает задел на будущее: если захочется добавить данные о здоровье или уровне голода, система будет легко масштабироваться.

Код для отправки через UdpClient получился максимально компактным. Тестирование с помощью короткого PowerShell-скрипта подтвердило: данные успешно уходят в сеть и корректно принимаются.

Получаемые по UDP данные
Мониторинг UDP-потока

Продолжение следует…

Первая фаза проекта прошла успешно. В следующей части я расскажу, как отрисовывал дизайн циферблата на Python и тестировал прошивку в симуляторе Wokwi, пока ожидал поставку железа. Приходилось ли вам автоматизировать игровые элементы? Делитесь опытом в комментариях!

 

Источник

Поделиться:

Похожие статьи

Поиск по играм, новостям и статьям…

Введите не менее двух символов

Введите не менее двух символов