Table of contents

В этом гайде рассмотрим, как подключить JSON к Unity и управлять настройками игры вне движка. На примере покажем, как подключить показатель скорости бега персонажа к редактору Ficher, и как менять эту характеристику без взаимодействия с Unity. Добавим в движок необходимые для этого скрипты и методы (весь код уже есть в материале).

Использовать такой способ можно с любыми показателями, так что вы легко сможете управлять разными параметры игры вне игровой платформы.

Создаем проект в Unity

Зайдите в Unity и создайте базовый проект на основе шаблона игры. Выберите 2D Platformer Microgame.

2D Platformer Microgame

После того, как создали проект, на экране появится его сцена. Раскройте иерархию объектов сцены (сайдбар слева) и найдите префаб Player. В инспекторе этого объекта (рабочая область справа) есть параметр Max Speed, который и будем изменять.

Inspector: Max Speed

Подготавливаем таблицы в редакторе Ficher

Проект в движке создан, теперь нужно внести игровой контент в таблицы.

Шаг 1: перейдите в редактор Ficher. Создайте новый проект, а в нем - таблицу с юнитами.

Шаг 2: назовите таблицу Units и добавьте следующие колонки:

Название колонки Тип Что содержит
speed Number Значение скорости юнита
name Text Имя (название) юнита
data Subtable Подтаблица, в которой будут размещены параметры юнита в зависимости от уровня: ловкость, сила, интеллект.
Table in a constructor
💡
В таблице на примере заведено больше значений, чем мы будем изменять в рамках этого кейса. Это сделано для того, чтобы показать, как работать с типом данных Subtable в Ficher и вложенными JSON.
Экспортируем данные из редактора

После того, как в таблицу редактора внесены нужные данные, их нужно извлечь.

Перейдите на вкладку Экспорт: для этого нажмите на соответствующую кнопку в правом верхнем углу.

Экспортируйте архив с таблицей (подробности, как работает экспорт в редакторе Ficher, показали и рассказали в отдельном материале).

Export

Таблица из конструктора при экспорте автоматически конвертируется в такой JSON:

[ { "id": 1, "speed": 10.0, "name": "Meeseeks", "data": [ {"id": 1, "level": 1, "agility": 1, "strength": 5, "intelligence": 10}, {"id": 2, "level": 2, "agility": 2, "strength": 6, "intelligence": 11}, {"id": 3, "level": 3, "agility": 3, "strength": 7, "intelligence": 12} ] }, { "id": 2, "speed": 1.0, "name": "Rimuru", "data": [ {"id": 1 ,"level": 1, "agility": 1.5, "strength": 4, "intelligence": 9}, {"id": 2, "level": 2, "agility": 2.5, "strength": 5, "intelligence": 10}, {"id": 3, "level": 3, "agility": 3.5, "strength": 6, "intelligence": 11} ] } ]

Добавляем скрипты в проект Unity

Перейдите в папку с проектом в движке или напрямую в файлах ПК. В папке Assets создайте папку Resources (в ней будут храниться библиотеки и конфиги).

Распакуйте файл экспорта из Ficher и загрузите в папку Resources.

Чтобы управлять JSON-ом внутри классов, нужно создать скрипт, описывающий структуру библиотеки, иначе чтение файла будет затруднено.

Создаем скрипт для управления JSON

Перейдите в папку Assets/Scripts/Model, где хранятся модели, описывающие JSON-структуры.

В этой папке создайте скрипт UnitsModel.cs и разместите следующий код:

using System.Collections.Generic; namespace Platformer.Model { [System.Serializable] public class Unit { public int id; public float speed; public string name; public Data[] data; } [System.Serializable] public class Data { public int id; public float agility; public float strength; public float intelligence; } }

Этот код содержит описание структуры данных, которые соответствуют таблице. Для каждой характеристики установлен тип данных float, так как в игре будем использовать дробные значения.

💡
Если не знаете, какой тип данных выбрать для характеристики, рекомендуем следующее:
• если в колонке содержатся числа - выбирайте integer (если однозначно уверены, что числа будут целые) или float (в остальных случаях).
• если в колонке текст - выбирайте string.

Важно: если добавите новую колонку или измените тип или название текущей колонки, то вам обязательно понадобится обновить данный файл.

💡
Квадратные скобки в свойстве “public Data[] data;” указывают на то, что в нем будет находиться массив с классами Data. Этот способ используется в том случае, если в редакторе Ficher используется тип данных Subtable.
Добавляем код для чтения скриптов

Переходим к добавлению кода для чтения скриптов, о которых писали ранее. Это необходимо сделать, потому что в Unity нет встроенного инструмента для чтения масcива JSON. Подробнее об этом можно почитать на форуме Unity и на StackOverFlow.

Для этого в папке Assets/Scripts/Model создайте скрипт JsonHelper.cs и добавьте в него код:

using System; using UnityEngine; namespace Platformer.Model { public static class JsonHelper { public static T[] FromJson(string json) { Wrapper wrapper = JsonUtility.FromJson>(fixJson(json)); return wrapper.Items; } public static string ToJson(T[] array) { Wrapper wrapper = new Wrapper(); wrapper.Items = array; return JsonUtility.ToJson(wrapper); } public static string ToJson(T[] array, bool prettyPrint) { Wrapper wrapper = new Wrapper(); wrapper.Items = array; return JsonUtility.ToJson(wrapper, prettyPrint); } public static string fixJson(string value) { value = "{\"Items\":" + value + "}"; return value; } [Serializable] private class Wrapper { public T[] Items; } } }

Этот код нужен для того, чтобы превратить массив [{…}, {…}] в объект {”items”: [{…}, {…}]}, а после извлечь значения. Это один из основных способов, который позволяет решить проблему управления JSON-объектами, используя встроенные инструменты Unity.

Редактируем настройки скорости персонажа

После того, как все скрипты загружены, необходимо подключить JSON в код самого персонажа и изменить значение скорости на нужное.

Чтобы сделать это, найдите скрипт PlayerController.cs в папке Assets\Scripts\Mechanics. Этот скрипт содержит логику определения скорости персонажа: свойство класса PlayerController: “public float maxSpeed = 3;”.

Чтобы изменить показатель скорости, нужно отредактировать PlayerController.cs.

Шаг 1

В класс PlayerController добавьте метод, который будет читать JSON и устанавливать нужное значение:

void LoadAndApplyJsonData() { // Reading JSON in raw form // !!! In case you use other tables, you need to change the table name "Units" here TextAsset jsonText = Resources.Load("Units"); // Converting raw JSON into classes // !!! For other classes, you need to replace "Unit" here. Unit[] units = JsonHelper.FromJson(jsonText.text); // Extract the "speed" from the first hero and set it to the class property "Max Speed" if (units.Length > 0) { Unit firstUnit = units[0]; maxSpeed = firstUnit.speed; // Debug code, to display nested json // Debug.Log(JsonUtility.ToJson(firstUnit.data)); } }
Шаг 2

Вызовите этот метод: для этого в методе Awake() добавьте вызов функции LoadAndApplyJsonData():


void Awake()
{
    health = GetComponent();
    audioSource = GetComponent();
    collider2d = GetComponent();
    spriteRenderer = GetComponent();
    animator = GetComponent();

    LoadAndApplyJsonData();
}

Готово! Конфиг можно использовать и редактировать данные в файле Units.json - при запуске проекта значения будут обновляться самостоятельно.

💡
Если вы работаете с движком Unreal Engine, то рекомендуем ознакомится с аналогичной статьей по подключению к нему JSON.

Вопросы

Слишком сложно. Зачем мне это использовать?

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

Можно ли избежать создания классов?

К сожалению, нет. Все способы так или иначе требуют создания дополнительных классов. Но, возможно, вы найдете полезным статью “Newtonsoft Json Unity Package”.

Если я сохраню данные в префабе или сцене, они обновят JSON-файл?

Нет, не обновят. Данные из сцен сохраняются в конфиги yaml в файлах Unity и не отправляются к нам на сервер. Вы можете самостоятельно реализовать такой функционал. Но при скачивании данных с Ficher результат может переписаться.

Я хочу, чтобы при сохранении данных в префабе данные отправлялись в Ficher. Возможно ли это?

Мы рассматриваем создание такого плагина. Если вы заинтересованы в нем - напишите нам на сервер Discord. Нам интересно, как вы используете Ficher, и какие задачи хотите решить с помощью этого плагина.