Игру правят несколько рук одновременно

У живого мира есть неприятное свойство: он работает, пока вы его правите. Игроки ходят по картам, мобы дерутся, сервер держит состояние в памяти. В этот же момент один человек меняет анимацию скорпиона, второй добавляет предмет в таблицу добычи, третий двигает переход между локациями. И это ещё до того, как к работе подключается ИИ-агент.

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

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

Контент разложен на элементы, у каждого — свой адрес

Игра здесь не монолит. Это сборка: фреймворк, библиотеки механик, миры с картами, анимации существ, наборы картинок предметов, префабы. Каждая из этих единиц — отдельная запись каталога: сейчас в нём 84 анимации, 27 наборов картинок, 8 миров, три библиотеки, фреймворк и сама игра.

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

Анимации существ в каталоге. Метка «sprite sheet» — покадровая нарезка, «по косточкам» — скелетная анимация; у записи с несколькими вариантами облика указано число сущностей внутри.

Так же устроены и локации: мир — это набор карт со своей графикой и своей раскладкой в открытом мире.

Записи миров: превью карт, входящих в мир. Мир целиком — такая же единица распространения, как одна анимация.

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

Мир Tulimshar: три карты, стыкующиеся в открытый мир. Кнопка «Получить» ставит мир в вашу игру, соседняя ведёт в его репозиторий.

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

Состав игры: фреймворк, клиент, библиотеки, 17 компонентов, 24 группы событий, 49 префабов, анимации и изображения. Каждый элемент — ссылка на свою запись каталога.

Git — это и бэкап, и конструктор

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

Верхнеуровневые группы проекта: gitlab.com/mmogick

Внутри группы — по репозиторию на ассет. Это не эстетика: репозиторий и есть идентичность ассета. По его адресу платформа понимает, что «этот скорпион» в вашей игре и «этот скорпион» в моей — один и тот же ассет разных версий, а не два разных существа с похожими именами.

Одна анимация — один репозиторий: gitlab.com/mmogick/animation/the-mana-world

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

Правки видны до того, как попадут в мир

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

Миры игры в админ-панели: у каждого свой коммит, отметка «обновление» (у источника есть версия свежее вашей) и «отправить» (у вас есть неопубликованные правки).

Ни одна операция не выполняется вслепую. Отправка в репозиторий, обновление из источника, откат — перед каждой показывается построчный список того, что изменится: красное уйдёт, зелёное придёт.

Тот же предпросмотр ниже по списку: файл, который будет удалён целиком, и построчные правки в соседнем файле.

Откат при этом разделён на две глубины: снять только свои правки — или полностью переустановить состав игры из репозитория. Данные игроков в первом случае не трогаются.

Откат к базовой версии: 61 файл различий, две глубины отката и построчный разбор — красное уйдёт, зелёное вернётся.

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

Контент остаётся у автора

Сервис не забирает игру себе. Репозитории с контентом принадлежат команде: игра целиком, миры, анимации, наборы картинок. Мой сервис — среда, которая эту игру запускает и держит живой мир, а не хранилище, из которого потом не выбраться.

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

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

Что это даёт на практике

  • Начать без установки: браузер и учётная запись — правки сразу в живой игре, локальная среда не нужна.

  • Работать командой: каждый в своей копии, правки собираются через репозитории, а не через «скинь мне архив».

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

  • Не бояться сломать: любая правка обратима, откат к базовой версии заранее показывает, что вернётся.

  • Собирать игру из готового: миры, анимации, наборы картинок, библиотеки механик ставятся как детали конструктора.

  • Делать своё из чужого: взяли ассет, поправили под свою игру, опубликовали свою версию.

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

  • Держать контент у себя: репозитории ваши, локальная правка возможна, сервис только запускает мир.

  • Переиспользовать между своими играми: один и тот же ассет живёт сразу в нескольких проектах.

Где здесь ИИ

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

Это и есть причина, почему схема работает. ИИ не решает, что считать одним ассетом, где проходит граница мира и что нельзя тянуть напрямую. Эти рамки задаю я, а машина внутри них исполняет — быстро и без усталости. Уберите рамки — получите ту самую «гору сгенерированного мусора», о которой любят писать в комментариях.

Чего ИИ не делает сам: не придумывает геймдизайн, не решает продуктовые развилки и не принимает решение «выкатывать или нет». Последнее слово — за человеком, который смотрит предпросмотр.

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

Зачем это всё

Собрать MMO в одиночку невозможно не потому, что код сложный, а потому что контента нужно много и он должен собираться в одно целое. Каталог готовых ассетов с историей версий превращает «нарисовать и запрограммировать всё самому» в «взять готовое, поправить под себя, опубликовать своё». Ровно этим я сейчас и занимаюсь: беру существующий мир, разбираю его на элементы и складываю обратно уже как контент платформы.

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

И главное, что даёт такой инструментарий, — контроль. Видно, кто и что изменил, правка вносится точечно в один элемент, а история сохраняется целиком — одинаково для человека и для машины.

У ИИ здесь есть рабочее место — те самые руки, про которые я писал в части про внедрение ИИ. Дальше начинается разделение труда: сам я работаю в Claude Code, рисование контента — карты, анимации — уходит к ChatGPT, а Claude проверяет результат, грузит его в репозиторий и в игру, гоняет тесты и выставляет нужные настройки. Получается не генератор текста, а исполнитель полного цикла, которому поручают кусок работы целиком.

Вопрос к тем, кто работал в команде над игровым контентом: что у вас чаще ломалось — рассинхрон версий ассетов, затёртые чужие правки или невозможность откатиться на «как было вчера»? Соберу боли под разбор в следующих частях.