Этот туториал — часть серии Начало работы — День 5, Неделя 1.
Проблема: дизайн и код расходятся
Вчера мы собрали папку Враги и наполнили её - для каждого врага это будет игровой объект с одинаковыми полями: health, speed, damage и size. Ребаланс происходит в приложении, и с точки зрения гейм-дизайна всё отлично.
Следующим шагом нам нужно показать все данные игровому движку, иначе рано или поздно настигнет другая проблема:
Дизайнер обновляет speed врага Посетитель-ходячий до 60. Программист, работая по старой заметке, работает со значением 30. Дизайн и код незаметно расходятся друг с другом, вызывая бесконечные споры о важных деталях. Это классический рассинхрон, как в известной басне про лебедя, рака и щуку.
Дисциплина и бесконечные созвоны тут не помогут. Решение в другом: движок должен подтягивать тот самый файл, который правил дизайнер. А для этого сам дизайн нужно превратить в понятный движку формат.
В IMS Creators есть возможность выгружать данные в кастомных форматах под конкретный движок, но об этом мы подробно поговорим позже. Сейчас рассмотрим самый простой и наглядный путь: разместим проект IMS Creators Desktop прямо в директории с Godot-проектом. Тогда дизайн и код окажутся по соседству, а данные лягут на диск рядом с движком - и движку не придётся долго искать, откуда их читать.
Почему именно JSON решает данную проблему
Игровой объект не зашит намертво внутри движка или редактора. На диске это обычный файл - например, Враги/Посетитель-ходячий.ima.json. По сути, мы имеем дело с чистым, структурированным JSON-форматом. А такой открытый JSON - это самый быстрый и прямой мост между дизайном и кодом:
- JSON - обычный текстовый формат, который умеет читать любая программа - без специализированного экспорта и без привязки к платформе.
- Он структурирован - числа остаются числами с теми же именами полей, что вводил дизайнер (
health,speed,damage,size), а не обычным текстом, который нужно парсить. - Он обновляется в момент сохранения - правите в IMS Creators, и вместе с вами меняется тот самый
.ima.json, который загружает движок.
Один файл, два потребителя: дизайнер правит его в приложении, движок читает его в рантайме. Когда значение меняется на стороне дизайна, движок при следующей загрузке считывает новое значение. Больше нет двух источников истины.
Откройте папку проекта и прочитайте данные полей
Посмотрим, что реально лежит на диске. Откройте папку проекта и откройте Враги/Посетитель-ходячий.ima.json в любом текстовом редакторе. Это JSON-документ с небольшим служебным блоком вверху - id, какие-то blocks и title элемента. Что важно для движка - секция values -> props, которая хранит именно те поля, что вы ввели:
{
"title": "Mall walker",
"values": {
"props": {
"damage": 8,
"speed": 30,
"health": 60,
"size": 1
}
}
}
Вот и всё - те же поля, что вы задали в приложении, лежат в простом, понятном для всех файле. Дизайнеру не нужно перепечатывать их для движка, а движку не нужно считывать их из обычного текста. К этому моменту и вёл весь наш предыдущий этап разработки: структурированные поля становятся данными, а данные - это то, что код может загрузить как есть.
Загрузите тот же файл в Godot
Теперь сторона движка - для примера возьмём реальный Godot-проект ("Dead Mall"): сцена с Хлоей и тремя врагами (Посетитель-ходячий, Посетитель-ходячий (бронированный), Обжора из фуд-корта), которые преследуют её. У каждого врага есть экспортируемый data_path, указывающий прямо на его .ima.json, а скрипт врага считывает speed и size обратно в сцену:
@export_file("*.json") var data_path: String
func _reload():
var file = FileAccess.open(data_path, FileAccess.READ)
var json_text = file.get_as_text()
file.close()
var json = JSON.new()
json.parse(json_text)
var props: Dictionary = json.data.get("values", {}).get("props", {})
speed = props.speed
scale = Vector2(props.size, props.size)
func _ready():
_reload()
Теперь Godot видит speed = 30 и size = 1 для Посетителя-ходячего - те же числа, что задал гейм-дизайнер в приложении. Враги преследуют Хлою, так что числа видно вживую: поднимите Скорость или Размер в IMS Creators, сохраните и перезагрузите сцену - и враг действительно побежит быстрее или станет крупнее.

Результат: один источник истины
Это то, к чему мы стремились всю неделю. Бестиарий больше не документ, который «информирует» разработчика, а тот в свою очередь всё держит в голову - это файл, который используется в коде игры:
- Никакой перепечатки. Никто заново не вводит
speedи не извлекает его из предложения. Движок читает поле напрямую. - Никакого расхождения. Ребаланс в приложении мгновенно становится информацией на диске, так что движок не может показывать устаревшие числа.
- Дружелюбно к git. Раз
.ima.json- это обычный текст, каждое изменение баланса можно просмотреть и откатить.
Разрозненные заметки стали папкой врагов, папка стала простыми файлами, простые файлы стали данными, которые загружает движок. Весь цикл от «идеи в голове дизайнера» до «числа в игре» - теперь одна папка, которую можно открыть.
Дальше: связываем персонажей и способности
Следующим шагом мы свяжем персонажей с их способностями через ссылки, чтобы переименование одного не ломало другое. Дизайн перестаёт быть изолированными файлами и становится сетью связанных элементов - а дальше мы продолжим следить, чтобы эта сеть и код синхронизировались.
Готовы увидеть свои числа в работающей игре? Скачайте IMS Creators, откройте папку проекта на диске (в реальном проекте она лежит в папке Враги), прочитайте один .ima.json в текстовом редакторе и загрузите те же поля в Godot уже сегодня: ims.cr5.space/desktop.
Готовы? Задайте полям настоящие типы - следующий пост в этой серии.
FAQ
Что именно находится в файле .ima.json?
Это обычный JSON-документ одного элемента. Помимо небольшого служебного блока (id и blocks), он содержит title элемента и, в разделе values -> props, введённые структурированные поля - например, health, speed, damage и size. Всё это стандартный JSON, который можно открыть в любом редакторе и игровом движке.
Нужно ли экспортировать что-то, прежде чем движок сможет это прочитать?
Нет. Файл .ima.json уже лежит на диске как обычный JSON в момент сохранения элемента. Чтение не требует шага экспорта - движок может загрузить файл напрямую. Экспорт в один клик - это отдельная тема дальше в серии.
Что, если мой движок ожидает другую структуру, чем values.props?
Не проблема. Файл - обычный JSON, так что вы можете разбирать его так, как нужно вашему пайплайну: пример выше читает values.props, но тот же файл легко сопоставить с любой нужной движку структурой всего парой строк кода. А если хочется совсем без парсинга, прямо в IMS Creators есть возможность настраивать формат экспорта под конкретный движок - тогда данные будут приходить уже в нужной структуре.
Заменяет ли это полноценный контроль версий?
Это его дополняет. Так как файлы - обычный текст, их можно коммитить в git и делать откат каждого изменения. Контроль версий - ваша страховка, открытый JSON - то, что изначально держит дизайн и код в согласии.
Перезапишет ли IMS Creators мой файл, если я отредактирую его вне приложения?
Нет - именно данные с диска служат источником правды, поэтому IMS Creators подхватит изменения, которые вы внесёте в файл со стороны. Тем не менее, пользоваться редактором IMS Creators намного удобнее: он понимает структуру элемента и аккуратно вносит правки, не рискуя случайно повредить служебные поля.