Этот туториал — часть серии Начало работы — День 5, Неделя 1.
Проблема: дизайн и код расходятся
Вчера мы собрали папку Враги и наполнили её - для каждого врага это будет игровой объект с одинаковыми свойствами: health, speed, damage и size. Ребаланс происходит в приложении, и с точки зрения гейм-дизайна всё отлично.
Следующим шагом нам нужно показать все данные игровому движку, иначе рано или поздно настигнет другая проблема:
Дизайнер обновляет speed врага Посетитель-ходячий до 60. Программист, работая по старой заметке, работает со значением 30. Дизайн и код незаметно расходятся друг с другом, вызывая бесконечные споры о важных деталях. Это классический рассинхрон, как в известной басне про лебедя, рака и щуку.
Дисциплина и бесконечные созвоны тут не помогут. Решение в другом: движок должен подтягивать тот самый файл, который правил дизайнер. А для этого сам дизайн нужно превратить в понятный движку формат.
В IMS Creators есть возможность выгружать данные в кастомных форматах под конкретный движок, но об этом мы подробно поговорим позже. Сейчас рассмотрим самый простой и наглядный путь: разместим проект IMS Creators Desktop прямо в директории с Godot-проектом. Тогда дизайн и код окажутся по соседству, а данные лягут на диск рядом с движком - и движку не придётся долго искать, откуда их читать.
Почему именно JSON решает данную проблему
Игровой объект не зашит намертво внутри движка или редактора. На диске это обычный файл - например, Враги/Посетитель-ходячий.json. По сути, мы имеем дело с чистым, структурированным JSON-форматом. А такой открытый JSON - это самый быстрый и прямой мост между дизайном и кодом:
- JSON - обычный текстовый формат, который умеет читать любая программа - без специализированного экспорта и без привязки к платформе.
- Он структурирован - числа остаются числами с теми же именами свойств, что вводил дизайнер (
health,speed,damage,size), а не обычным текстом, который нужно парсить. - Он обновляется в момент сохранения - правите в IMS Creators, и вместе с вами меняется тот самый
.json, который загружает движок.
Один файл, два потребителя: дизайнер правит его в приложении, движок читает его в рантайме. Когда значение меняется на стороне дизайна, движок при следующей загрузке считывает новое значение. Больше нет двух источников истины.
Откройте папку проекта и прочитайте данные полей
Посмотрим, что реально лежит на диске. Откройте папку проекта и откройте Враги/Посетитель-ходячий.json в любом текстовом редакторе. Это JSON-документ со свойствами на верхнем уровне в виде прозрачных пар «имя: значение» - health, speed, damage, size - плюс небольшой объект __meta, хранящий служебную информацию (id, название и метаданные блоков элемента):
{
"health": 60,
"speed": 30,
"damage": 8,
"size": 1,
"__meta": {
"id": "element:...",
"title": "Mall walker",
"parentIds": []
}
}
Вот и всё - те же свойства, что вы задали в приложении, лежат в простом, понятном для всех файле. Дизайнеру не нужно перепечатывать их для движка, а движку не нужно считывать их из обычного текста. К этому моменту и вёл весь наш предыдущий этап разработки: структурированные свойства становятся данными, а данные - это то, что код может загрузить как есть.
Загрузите тот же файл в Godot
Теперь сторона движка - для примера возьмём реальный Godot-проект ("Dead Mall"): сцена с Хлоей и тремя врагами (Посетитель-ходячий, Посетитель-ходячий (бронированный), Обжора из фуд-корта), которые преследуют её. У каждого врага есть экспортируемый data_path, указывающий прямо на его .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 data: Dictionary = json.data
speed = data.speed
scale = Vector2(data.size, data.size)
func _ready():
_reload()
Теперь Godot видит speed = 30 и size = 1 для Посетителя-ходячего - те же числа, что задал гейм-дизайнер в приложении. Враги преследуют Хлою, так что числа видно вживую: поднимите Скорость или Размер в IMS Creators, сохраните и перезагрузите сцену - и враг действительно побежит быстрее или станет крупнее.

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