Почти 50 дней я пытаюсь сделать навигацию для слепых в закрытой игре

Я уже почти 50 дней делаю мод доступности для Resonance: A Plague Tale Legacy. Идея — дать незрячим и слабовидящим игрокам что-то похожее на навигационную помощь из The Last of Us Part II: не автопрохождение, а понятные подсказки, куда идти, как пройти реальным маршрутом и какое действие сейчас нужно выполнить.

Начиналось всё довольно наивно. Я понимал, что будет сложно: закрытый движок Asobo, исходников нет, SDK нет, нормальной документации по внутренним системам тоже нет. Но я не думал, что почти через 50 дней всё ещё буду в основном воевать не с кодом, а с пониманием того, что вообще нужно делать дальше.

Самый сильный контраст я вижу на обычной разработке. У меня есть готовое Android-приложение, и если я хочу внести в него семь изменений, нейросеть вполне может за один заход разобрать проект, поправить семь мест, добавить новую логику и выдать рабочие файлы. Я проверяю, нахожу пару косяков, потом уже вместе с ней полирую результат. Это реально удобно.

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

А теперь другая задача: сделать навигацию для слепых в игре на закрытом собственном движке, причём приблизиться хочется к уровню системы, аналог которой по сути есть только в The Last of Us Part II. Публичного технического описания того, как она там устроена, нет. По движку Resonance нейросеть почти ничего не знает. И вот тут вся магия заканчивается.

Почти каждый шаг приходится контролировать

Сетка может очень быстро написать код, разобрать бинарник, построить индекс, найти тысячи связей, нагенерировать десяток исследовательских скриптов и уверенно объяснить, почему именно эта ветка сейчас критически важна. Проблема в том, что она очень плохо понимает, приближает ли всё это к реальной цели.

Если я начинаю просто писать «дальше», через несколько шагов почти гарантированно обнаруживаю, что мы уже полдня исследуем какую-нибудь узкую цепочку, которая технически любопытна, но для навигации Софии не даёт вообще ничего. Или модель снова копает то, что уже было исследовано две недели назад. Или начинает чинить локальную проблему, не замечая, что сама архитектура вокруг неё неправильная.

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

Как я однажды поверил, что у нас уже есть модульная система

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

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

Причём местами это уже доходило до абсурда. Некоторые исследовательские скрипты зависели от захардкоженного пути к README и от того, что именно написано внутри этого README. То есть техническое исследование движка могло незаметно зависеть от текста документации в конкретном месте на диске. Формально файлов стало больше и назывались они красивее, но единого движка от этого не появилось.

Когда я наконец полез проверять всё нормально, пришлось сначала разбирать накопившуюся документацию и инструменты, а потом фактически заставлять проект реализовать ту архитектуру, которую я просил изначально. Не просто «раздели код на модули», а реально сделать единый runtime: наблюдение мира, физическая навигация, traversal, сюжетный слой и координатор, которые обмениваются понятными данными и не пытаются параллельно управлять одним и тем же.

Сейчас этот переход уже произошёл. Исследовательская свалка наконец начинает превращаться в один навигационный движок. Даже тут без очередных приколов не обошлось, но это неважно.

Потом пришлось делать ещё и SDK

Следующая проблема была очевидной: реверс-инжиниринг идёт слишком медленно. Закрытый EXE и огромный All.psc приходилось снова и снова исследовать отдельными скриптами, а результаты легко терялись среди сотен предыдущих попыток. Поэтому я начал отдельный reverse-engineering SDK для движка — не часть мода, а инструмент, который должен массово индексировать EXE и игровые скрипты, восстанавливать проверяемые связи и отдавать модулю уже более осмысленные данные.

И тут началась ровно та же борьба.

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

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

Наверное, с большим опытом я плыл бы быстрее

Тут важно понимать ещё одну вещь: задача сама по себе ненормальная. Я совсем не уверен, что любой опытный программист или reverse engineer взял бы такой проект и быстро довёл до результата. Тут одновременно нужно разбираться в закрытом движке, runtime-состоянии игры, pathfinding, сценарных системах, переходах между разными типами перемещения и ещё понимать, что вообще требуется незрячему игроку. Даже среди профессионалов далеко не каждый занимается таким набором вещей.

Но если бы у меня было профильное образование или несколько лет опыта в разработке, программировании, reverse engineering или хотя бы в работе с AI-системами, я почти уверен, что сейчас был бы заметно ближе к финишу. Я быстрее видел бы, где модель несёт ерунду, раньше замечал бы плохую архитектуру и меньше времени тратил бы на красивые технические тупики и, возможно, чётче понимал бы как общую архитектуру, так и детальные шаги.

Пока ощущение скорее такое, будто я посреди океана и пытаюсь по изменчивому ветру понять, хотя бы в правильную ли сторону плыву. Иногда появляется настоящий работающий маршрут, игра отдаёт нужное состояние, переход удаётся наблюдать — и кажется, что вот оно. Потом следующий участок снова разваливается на десяток неизвестных.

ИИ при этом всё равно делает возможным сам факт такого проекта. Без него я бы вообще не полез разбирать закрытый движок и писать всё это. (хоть я уже в который раз задаюсь вопросом «нафига я в это полез и почему всё ещё не бросил). Но чем уникальнее задача и чем меньше у модели готовых похожих примеров, тем сильнее меняется её роль. Она перестаёт быть чем-то, что знает, как надо, и становится очень быстрым инструментом, за которым нужно следить почти на каждом шаге.

44
22