Как я делаю Dungeon Cult: 13 нейросетей снаружи, игровой ИИ внутри

В первой статье я показывал, как делаю существ для Dungeon Cult - игры про строительство подземелья в духе Dungeon Keeper, но с лавкрафтовскими обитателями. На этот раз - как управлять таким проектом и, конечно, про само подземелье: как заставить его работать. Проект я делаю вместе с ИИ-агентами. Они пишут код и инструменты, собирают ассеты и запускают проверки. Но внутри игры монстры не обращаются к языковой модели. У них обычная игровая логика на C++. Это два разных ИИ, которые дальше лучше не путать.
Заодно разберу 13 ИИ-моделей и сервисов, которые успели поработать в проекте или пройти через наши тесты: от агентов, пишущих код, до генерации картинок, 3D, голосов и музыки. Что запускал локально, что оказалось открытым, что прижилось, а что осталось экспериментом - собрал в одной таблице.
Как устроено подземелье
Сначала несколько слов про суть игры - есть 2 (пока что) хранителя, каждый из них копает и строит комнаты, следит за своими существами (кормит, тренирует, чекает настроеие, отправляет воевать и тд). Побеждает тот, кто первый разрушил вражеский центр подземелья (сердце). Игрок (хранитель) выступает в роли бога, который этим подземельем управляет.
Вспомним, как стартовала разработка. Начиналось всё с веб-прототипа и нескольких изометрических вариантов. Картинки были, производительность и поведение не радовали. Потом переехали в Unreal и полноценное 3D - и быстро выяснили, что красивое помещение ещё не стало подземельем. Один из ранних вариантов мира приезжал из Blender цельной статической моделью. Выглядеть он мог как угодно, но игра не знала, где в нём отдельная клетка породы, чья это земля и что изменится после удара рабочего. Копать такую декорацию было нечем. Поэтому основой стал массив клеток: порода, открытый пол, присвоенная земля, комнаты. А уже поверх этих данных Unreal рисует геометрию повторяющимися экземплярами моделей. Мебель комнат тоже не вся нейросетевая: часть собирали скриптами в Blender, с отдельными осями для подвижных деталей.
ИИ хранителя и ИИ существ
У меня два уровня управления. Хранитель занимается хозяйством: планирует копку, строит комнаты, нанимает рабочих, выбирает исследования и собирает отряд. У отдельного существа свои заботы: поесть, поспать, полечиться, поработать или драться. Под капотом - Utility AI: своя реализация на C++, где мирные занятия получают численную оценку полезности. На неё влияют голод, усталость, здоровье, склонности вида и расстояние до нужной комнаты. Нет подходящей комнаты - нет и этого варианта. Это не обученная нейросеть: правила и коэффициенты заданы в проекте, многие вынесены в отдельный конфиг.
Пример с текущими коэффициентами: допустим, чтение набрало 0,70. Существо уже читает, поэтому получает ещё 0,15 за продолжение - итого 0,85. При голоде 70 из 100 оценка еды достигает 0,88 и при прочих равных побеждает. Решение обычно пересчитывается раз в 0,5–0,7 секунды, но доступное занятие удерживается минимум 3 секунды, если не вмешалось внешнее событие. Такое удержание называют гистерезисом: небольшой перевес не заставляет монстра каждые полсекунды разворачиваться между книгой и курицей. Бой и бегство обрабатываются отдельно от этого выбора мирных занятий.
У хранителя - планировщик на правилах с оценками срочности. Например, отсутствие курятника даёт стройке 0,95, а необходимость первой библиотеки - 0,80. Когда обе задачи допустимы, еда важнее исследований. Но это не просто сортировка списка: учитываются деньги, условия развития и уже начатая работа. Зал, который сейчас копают, не бросается из-за нового желания. Поэтому для отладки полезнее видеть «курятник: 0,95, нет еды», чем просто «ИИ решил строить».

Самая полезная просьба агенту здесь - не «улучши ИИ», а «запиши, почему он выбрал это действие». В журнале нужны существо, время, цель и причина. На видео видно, что кто-то тупит. Из журнала уже можно понять, что ему не хватило места, денег или доступного пути.
Как существа получили голоса
Существам нужны не только движения, но и звуки: рычание, дыхание, крик от боли, шум атаки. Начинали с ElevenLabs, затем попробовали локальные модели. В итоге большую часть новых голосов и эффектов подбирали в Stable Audio 3 Medium, прямо на моём ПК. Сначала пытались делать сразу полный набор звуков для персонажа. Неудачная идея: для одного существа пришлось забраковать все 45 вариантов - голос просто ему не подходил. Теперь сначала выбираем характер на паре звуков. Если рык подходит, делаем остальные реакции. Если нет - не тратим время на целую пачку.
Но хороший аудиофайл - ещё не хороший звук в игре. Например, рабочий уже ударил киркой, а удар слышен позже. Выяснилось, что перед самим стуком в записи почти секунда разгона. Обрезали начало - звук совпал с движением. Поэтому при рассинхроне стоит проверить и момент запуска, и сам файл. И обязательно слушать всё в толпе. Один монстр рычит убедительно, десять одновременно - уже гул. У одного из персонажей мы ограничили голос атаки одним срабатыванием в 8 секунд, а звук самого заклинания оставили на каждый выстрел. Так атаки слышны, но существо не орёт без остановки.
Проверка в массовом бою

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

Ролик снят с фиксированным шагом симуляции, поэтому выдавать его за замер FPS я не буду. Мне сейчас важнее связать всё в одну работающую сцену: чтобы существо выбрало цель, дошло, ударило, попало и издало звук именно в этот момент. На каждом из этих глаголов нашлась своя маленькая проблема.
Какие ИИ в итоге пригодились
Собрал весь набор, который использовал в разработке, ассетах и сюжетных роликах. «Лучшее» здесь - что прижилось у меня, а не рейтинг моделей вообще. Версии агентов менялись, поэтому Sol, Astra и Opus называю семействами.
Модель или сервис | Открытость | Для чего и что в итоге |
|---|---|---|
Нет, закрытая | Решение простых задач | |
Нет, закрытая | Основная модель от чата ГПТ | |
Нет, закрытая | Лучшая модель в проекте, решает самые сложные задачи, справляется чаще лучше Astra | |
Нет, закрытая | Основной путь для образов существ и иллюстраций. Для сюжетных кадров использовал gpt-image-2 | |
Да, MIT* | С него начинали перевод существ в 3D. Для новых моделей основной выбор сменился на Pixal3D: на нашем культисте TRELLIS склеил щупальца на лице | |
Да, MIT* | Текущий выбор для новых 3D-существ. На том же исходнике щупальца разделились; проверка сетки дала 4 открытых ребра против 5629 у TRELLIS. Это один пример, не общий бенчмарк. Доводка всё равно нужна | |
Нет, закрытая | Первые игровые звуки; кирка и сердцебиение остались в проекте. Для дальнейшего подбора голосов активно перешли к локальным моделям | |
Да, Apache 2.0 | Локальные пробы звуков существ. Основным инструментом не стал: дальнейшие подборки делали в Stable Audio. Это выбор нашего процесса, не доказательство, что MOSS хуже во всём. Но качественно не подошел | |
Открытые веса; Community License, не свободная MIT/Apache | Основной локальный инструмент для голосов существ и эффектов. Забраковывали отдельные подборки, но после докрутки итог устраивал | |
Да, MIT* | Локальная фоновая музыка. Принятые треки уже подключены; этот путь оставили рабочим | |
Нет, закрытый сервис | Отдельный эксперимент с музыкой: получили два варианта, но в игру их не подключали. Пока проба, а не замена ACE-Step | |
Нет, закрытая | Голос ранних сюжетных роликов, варианты Ash и Onyx. В ролике с Проводником затем использовал уже свой голос (про ролик будет в отдельной статье) | |
Да, MIT | Локально распознавал мою запись: по словам собирали нарезку и субтитры. Это не генератор голоса, а помощник при монтаже (про ролик будет в отдельной статье) |
* Указал лицензии основных проектов; у зависимостей могут быть другие условия. Локальный запуск сам по себе не означает open source. У Stable Audio есть ограничения Community License. И лицензия модели не даёт автоматически прав на чужую музыку для обучения LoRA или каверов - это отдельный вопрос перед релизом.
Чтобы проект не остался в переписке
Ещё я сделал себе отдельную локальную страницу — карту проекта. Когда существ, заклинаний и звуков стало много, вспоминать по чатам, что уже работает, стало неудобно. В карте собраны существа, комнаты, анимации, магия, аудио и оба уровня игрового ИИ.
Самое полезное - не одна галочка «готово», а раздельные состояния. Модель может быть принята внешне, но ещё не иметь нормальной атаки. Звук может лежать на диске, но не вызываться игрой. Поэтому «файл создан», «подключено» и «я посмотрел и принял» - разные вещи. После работы агенты фиксируют в файлах проекта, что поменяли, чем проверили, что не получилось и какой следующий шаг. Часть сведений карта собирает автоматически из ассетов и конфигов; оценки качества и причины отказа приходится записывать отдельно. Это не волшебная память, которая сама всё знает.
Практический совет: добавьте к задаче агенту требование «после выполнения обнови карточку: результат, путь к проверке, ограничения, следующий шаг; не ставь “принято” без моего просмотра». Новый чат тогда начинает с состояния проекта, а не с пересказа предыдущих десяти разговоров.


На выходе - существа уже ведут себя достаточно разумно, а ИИ хранитель способен неплохо посоревноваться с игроком. В следующих статьях я продолжу рассказывать о своем прогрессе.
О сотрудничестве и нетворкинге
Сам я работаю в hh.ru, а Dungeon Cult - мой личный проект. Готов к сотрудничеству и открыт к разным предложениям - по игре, инструментам или совместным экспериментам с ИИ. Если видите, что можем сделать вместе, напишите мне в личные сообщения на Хабре :)
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.