Создаем реальный индикатор кислорода из Subnautica: часть 1
Консоль управления при старте игры
Если задуматься, то игр, чье действие разворачивается преимущественно в водной среде, не так уж много. Я погружался в эстетику подводного города Восторг в BioShock, боролся за выживание в Barotrauma и изучал безмятежные океаны ABZÛ. Но ни один из этих проектов не вызывал у меня такого спектра эмоций, как Subnautica. Это тот редкий случай, когда планируешь «заскочить на часок», а обнаруживаешь, что за окном глубокая ночь.
Сейчас в раннем доступе появилась вторая часть, и для меня это стало отличным поводом вернуться к оригиналу. При погружении единственным по-настоящему важным индикатором становится уровень кислорода. Он — ваш главный советчик: стоит ли плыть дальше или пора спешно возвращаться на поверхность. Синтетический голос, монотонно произносящий «oxygen», звучит как приговор, когда времени на раздумья уже не осталось. Именно тогда меня посетила мысль: было бы здорово перенести этот счетчик из виртуальности в физический мир. Так родился этот любопытный DIY-проект.
Мир Subnautica — это планета, поглощенная бесконечным океаном. Атмосфера пригодна для дыхания, но основная часть жизни скрыта под толщей воды. После крушения корабля «Аврора» главный герой оказывается в спасательной капсуле посреди пучины. Единственный шанс выжить — адаптироваться к чужеродной среде и научиться использовать доступные ресурсы.
Именно тогда жизненно важным спутником становится счетчик кислорода. Он превращается в вашего главного друга, арбитра и палача. На нем отображаются две ключевые цифры: текущий запас воздуха и максимально возможный в данных условиях.

Пока у героя нет специализированного снаряжения, запаса хватает лишь на пару десятков секунд. По мере прогресса этот лимит растет, что мгновенно отражается на индикаторе.
Задача проста: считывать эти значения в реальном времени и выводить их на внешний девайс. Алгоритм действий таков: получение данных из игрового процесса, передача их на микроконтроллер и отрисовка интерфейса. Самый сложный этап — первый, так как всё зависит от особенностей игрового движка.
Первый взгляд
Стало очевидно: Subnautica — идеальная площадка для экспериментов. Разработчики из Unknown Worlds Entertainment проявили завидную лояльность к моддинг-сообществу. Для игры уже существуют удобные инструменты, такие как фреймворк Nautilus и загрузчик BepInEx. Их я и решил использовать.
Альтернативные методы, вроде прямого чтения памяти (привет, ArtMoney) или захвата экрана с распознаванием образов, показались мне слишком ненадежными: любой апдейт игры мог бы «сломать» всю систему. Для внешнего дисплея я выбрал круглый экран 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-скрипта подтвердило: данные успешно уходят в сеть и корректно принимаются.

Продолжение следует…
Первая фаза проекта прошла успешно. В следующей части я расскажу, как отрисовывал дизайн циферблата на Python и тестировал прошивку в симуляторе Wokwi, пока ожидал поставку железа. Приходилось ли вам автоматизировать игровые элементы? Делитесь опытом в комментариях!
Sony показала прозрачные геймпады DualSense и панели для PS5 в стиле эстетики 90-х
TrendForce прогнозирует: Apple займет треть рынка складных смартфонов в следующем году, но не обгонит Samsung
Microsoft впервые с 2018 года кардинально обновила DirectX Raytracing, ускорив трассировку лучей
Boeing впервые за полвека запустила производство лайнеров 737 MAX 10 на новом заводе
Гигантский выброс плазмы длиной 500 тысяч километров зафиксирован на Солнце
С начала года Rutube отразил свыше 530 DDoS-атак на фоне роста активности хакеров
Количество активных устройств с Яндекс Браузером превысило 100 миллионов
Virgin Galactic показала космический корабль Apeiron и перенесла туристические полёты на 2027 год