Lego или счастливое детство

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

О том, как мы попытались воспроизвести ту атмосферу, но уже в виде компьютерной игры и добавили в игру голоса семьи, применяли искусственный интеллект и проходили азы игростроения — расскажу в этой статье.

Первый релиз: уроки indie-разработки

Одной из самых наших любимых игр была Heroica. Это настольная игра, где необходимо выполнять задания, собирать ключи, драться с врагами. 

Игра Heroica. Одна из самых любимых игр нашей семьи
Игра Heroica. Одна из самых любимых игр нашей семьи

После того, как сын Воля уже в школе прошёл курсы Unity, решили закрепить знания и создать небольшую игру. Выбор пал на старую добрую Heroica. 

Мы работали по Agile: разбивали задачи на спринты, проводили дейли-митинги и ретроспективы — как настоящая команда, и на первую версию ушёл примерно год. 

Сталкивались с задачами, с которыми сталкивается любой инди-разработчик:

  • создали мини-движок для быстрого прототипирования уровней

  • реализовали выбор оптимального пути для ботов, для этого использовали алгоритма коммивояжёра

  • прорабатывали баланс уровней

  • оттачивали игровой процесс и другое

Вся графика была создана сыном. Нас вдохновляла оригинальная Heroica, многие элементы которой мы скопировали. 

В 2022 году опубликовали игру в AppStore и Google Play, но кроме наших знакомых и несколько десятков китайцев (для которых мы даже выпускали новогодние патчи) она никого не заинтересовала. Хотя мы получили интересный и полезный опыт. 

Скрины с нашей первой версии игры
Скрины с нашей первой версии игры

От настолки к AI: как мы оживили игру голосом

Прошло еще несколько лет, и в этом году дети поступают в университеты - и пока было свободное время после ЕГЭ, решили вернуться к игре: исправить небольшие ошибки, улучшить графику, добавить новые фичи и перевыпустить игру еще раз. 

При создании игры мы придерживались миссии - перенести атмосферу «ламповой» настольной игры в электронный вид, воссоздать ту атмосферу, когда мы играли все вместе, переговаривались и шутили. 

«Значит надо добавить в игру голос» - решили мы. С развитием LLM стало возможным «на лету» генерировать осмысленные комментарии и тут же их озвучивать. Начали размышлять, как это можно реализовать.

Наши размышления по реализации комментариев
Наши размышления по реализации комментариев

Вариант 1. Разместить небольшую LLM и модуль TTS внутрь самой игры. Однако в таком случае игра увеличится в объёме, на некоторых устройствах может плохо функционировать, так как будет недостаточно мощности телефона. Этот вариант признали далеко не идеальным.

Вариант 2. Запустить веб-сервис, к которому будет обращаться игра. На сервере разместить LLM и модули озвучивания. Мы оценили, что задержка составит примерно 4–5 секунд (в лучшем случае), что сделает реакцию на события игры слишком медленной. К тому же такая реализация требует постоянного подключения к интернету, поэтому отказались и от этого варианта.

Вариант 3. Использовать упрощённый подход. Игра достаточно однообразна, число возможных ситуаций и выражений ограничено («рыцарь вступил в бой», «маг открыл дверь»). А что, если заранее сгенерировать все возможные комментарии и выбирать их по игровой ситуации? Эта идея показалась нам наиболее простой и привлекательной.

И мы приступили к реализации

Сначала добавили формирование описания игровой ситуации в виде тегов. 

Событие: «Ход Рыцаря, он кинул кубик - и выпало 3, рыцарь походил», формируем тэги: [Рыцарь, Выпало 3, Походил]

Событие: «Ход  Мага, он находится в режиме боя, кидает кубик - выпало 4, Победа» - формируем тэги: [Маг, Режим боя, Выпало 4, Победа]

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

Для того, чтобы получить текстовые комментарии всю эту последовательность тегов подали на вход в LLM: нам помогали ChatGPT, DeepSeek, Qwen. В промте просили менять акценты: например, сгенерировать веселую фразу, обидную шутку, философскую фразу и так далее.

Большое количество фраз формировали сами, добавляли наши семейные моменты, например, про нашего кота Сырника (вот он на картинке, думает: «Зачем и меня вплели в эту затею»).

Настоящее фото кота по имени Сырник (не нейросеть)
Настоящее фото кота по имени Сырник (не нейросеть)

Сначала предполагали получить список фраз и использовать TTS (Text-to-Speech), но дочь Алена предложила записать наши «живые» голоса, как мы играли в детстве.

«Супер! Так и сделаем» — решили мы.

Записать большое количество фраз в домашних условиях — задача непростая, пришлось сократить их количество и выбрать наиболее повторяющиеся, таким образом, у нас получилось 280 уникальных фраз которые необходимо озвучить.

Как мы записывали голос

Мы создали JSON-базу, где каждая фраза связана с комбинацией из 5 тегов.

Фрагмент JSON файла ниже.

{
    "tags": ["текущий ход", "Knight", "бросил кубик", "Knight", "выпало3"],
    "text": "Ну Knight, бросок — как обычно, тройка. Снова не везёт!",
    "audioClipName": "vl_knight_001.wav"
  },
  {
    "tags": ["ход", "Knight", "сделал ход", "Knight", "текущий ход"],
    "text": "Knight снова на подъёме! Ход сделан, цель найдена.",
    "audioClipName": "vl_knight_003.wav"
  },
  {
    "tags": ["бросил кубик", "Knight", "выпало2", "режим боя", "Knight"],
    "text": "Выпало 2... Видимо, сегодня не день для атаки.",
    "audioClipName": "vl_knight_004.wav"
  },
  {
    "tags": ["False", "режим восстановления", "Knight", "ход", "Knight"],
    "text": "Knight в порядке, но предпочитает пока ходить без риска.",
    "audioClipName": "vl_knight_005.wav"
  },

Дополнительно добавили промежуточные комментарии:

  • Начало боя: «Давай!», «Вперед!», «Мы в тебя верим!»

  • Проигрыш в бою: «Ну вот», «Плохо», «Не расстраивайся».

  • Выигрыш в бою: «Ура», «Победа!»,  «Молодец!»

  • Подгонялки: если игрок задерживается дольше 10 секунд, голос напоминает: «Ну давай, не спи»

Одну и ту же фразу озвучивал каждый член семьи: я, жена, дочь и сын. Записывали голоса на iPhone, микрофон у него хороший, конечно, не обошлось без ошибок, но это только добавляет «ламповости». 

Подготовить 280 фраз непросто, важно, чтобы имя файла соответствовало фразе и соответствующим тегам. Человеку сложно проговорить 280 фраз и ни разу не ошибиться, поэтому записывали отрезками по 50 фраз и скриптом Python автоматически нарезали на отдельные файлы, определяя границу фразы по паузе между ними.  Далее добавили файлы в Unity.

Скрин последней версии игры
Скрин последней версии игры

Как работает система подбора реплик

Алгоритм подбора фраз реализован следующим образом.

  1. Генерация тегов. Система по ключевым событиям игры генерирует теги, например: [Маг, Битва, Проигрыш]. Все теги собираются в единую последовательность в разрезе одного уровня.

  2. Контекст из 5 тегов. Для анализа мы используем 3 тега текущего хода + 2 тега с предыдущего, чтобы получить связь с прошлым ходом. 

  3. Реакция на каждое пятое событие. Четыре из пяти событий мы пропускаем, иначе боты были излишне «болтливыми». 

  4. Сопоставление с базой. На каждое пятое событие система ищет точное совпадение с одной из 280 комбинаций по пяти тэгам.

  5. Случайный выбор. Для наиболее распространенных последовательностей тегов создали разные варианты фраз. Например, одна из популярных комбинаций выглядит так: [Маг, Выпало 4, Походил], и использование одной единственной фразы приводит к однообразию, поэтому на такие комбинации записали несколько вариантов, из которых система случайным образом выбирает один. Выбор персонажа, произносящего фразу, также осуществляется случайно. 

  6. Ограничение на повторы. Фраза, однажды произнесённая, повторно на данном уровне не повторяется. 

    Таким образом система описывает игровую ситуацию через теги и подбирает соответствующую реплику, еще между делом вставляем промежуточные комментарии. Результат нас вполне удовлетворил.

Морской уровень
Морской уровень

Итог

В итоге у нас получилась электронная копия нашей семейной игры. Много лет назад мы играли в нее все вместе, а теперь можно поиграть на телефоне и услышать наши голоса.

Игра называется Magic Crystal Board Game

Если у вас будет минутка, скачайте игру, оставьте отзыв - и вы окажитесь вместе с нами за игровым столом. 

Комментарии (0)


  1. Jijiki
    17.09.2025 08:25

    прикольно выглядит, посмотрев на крайний скриншот, успехов