Созданию простого 2D платформера посвящено немало публикаций на ресурсах для разработчиков игр. В качестве движка часто используют Unity, а для создания карт — Tiled Map Editor. Взаимодействие этих двух сред осуществляется с помощью бесплатной утилиты Tiled2Unity, которая создает из TME файлов префабы в Unity.
Как это работает, расскажем на примере разработки нашего платформера “X-Drums”.
Двигаться будем по следующей схеме:
Итак, у нас есть проект в Unity и есть карта, созданная в Tiled Map Editor. Запускаем Unity и импортируем Tiled2Unity.unitypackage.

В Tiled Map Editor вызываем окно редактирования команд:

Добавляем новую команду, в которой прописан путь до исполняемого файла Tiled2Unity.exe. Вместо %mapfile Tiled автоматически подставит путь к файлу карты. Последний аргумент этой команды — это путь к папке Tiled2Unity, которая должна была появиться в проекте после импорта.

Запускаем команду и в появившемся окне нажимаем большую кнопку.

В результате экспорта получаем префаб карты, который находится в папке Tiled2Unity. Размещаем этот префаб на сцене в Unity. Теперь при работе с картой в TME и ее экспорте, префаб и объект на сцене будут изменяться в соответствии с изменениями в TME.

Так мы настроили экспорт карты из Tiled в Unity и создали игровую среду.
Теперь займемся настройкой объектов на нашей карте.
2. Редактор столкновений
В первую очередь, определим элементы игрового пространства, которые будут препятствиями для героя. Это пол, стены, софиты на потолке, а также барабаны, выступающие платформами, по которым и будет прыгать герой.
Запускаем редактор столкновений в Tiled:

Выбираем нужный нам тайл, к примеру, часть барабана, и редактируем полигоны:

Аналогично редактируем другие нужные нам тайлы (пол, стены и т.д.). В результате, при экспорте Tiled2Unity автоматически создаст коллайдеры PolygonCollider2D, которые и будут выступать для героя препятствиями.


Однако другие объекты игры, с которыми может взаимодействовать герой, являются более сложными. Поведение тарелок, фанаток, нот и других элементов контролируется с помощью компонентов и скриптов. Для экспорта таких объектов необходимо указывать им дополнительные параметры в Tiled и затем обрабатывать их в Unity.
Впрочем есть список параметров, которые мы можем использовать в Tiled без настройки их в Unity, поскольку Tiled2Unity уже сделал это за нас. Среди них:
Зададим нужные нам параметры для барабанных палочек, по которым будет прыгать герой:

При экспорте в Unity получаем такой результат:

Слою задан параметр OneWayPlatform, он используется для объектов, которые являются проницаемыми снизу.

Обработку других параметров, назовем их “пользовательскими”, и экспорт объектов с такими параметрами, мы будем настраивать в Unity. Задавать их в Tiled можно как для слоев (объектов), так и для объектов. В разных случаях может бы��ь удобным первый или второй вариант. Рассмотрим, как это реализовать.
4.1. Пользовательские параметры для слоев (объектов)
Зададим пользовательские параметры для слоя. Этот вариант мы используем для однотипных объектов. В нашей игре такими являются тарелки и ноты. Их особенность в том, что они одинаково взаимодействуют с героем и не нужно их отличать друг от друга.
Создаем слой объектов в Tiled и размещаем на нем наши тарелки. Затем, задаем параметр AddObject для всего слоя.

Поле своих параметров для каждой тарелки остается пустым.

Теперь переходим в Unity, где для тарелок мы создали префаб и привязали к нему скрипт, определя��щий их поведение при прыжке героя — они падают и возвращаются в исходное положение.
Напишем код, который при импорте тарелок для каждого объекта из Tiled создаст экземпляр нашего префаба. Для этого создаем скрипт CustomTiledImporterForHiHats с классом, который наследует интерфейс Tiled2Unity.ICustomTiledImporter и атрибутом [Tiled2Unity.CustomTiledImporter].
Этот скрипт Tiled2Unity будет вызывать для каждого импортируемого из Tiled слоя и объекта. А обрабатываться, соответственно, будут те слои или объекты, у которых среди параметров есть параметр AddObject со значением “Hi-hat”.
Скрипт готов, и мы можем экспортировать тарелки.

И вот так герой взаимодействует с ними.

Экспорт нот настроен точно так же как экспорт тарелок. Единственное отличие в том, что в игре есть несколько видов нот с разной стоимостью в зависимости от цвета. Поэтому для каждого типа нот со своим номиналом мы создали префаб в Unity и слой объектов в Tiled, указав ему в параметре AddObject тип ноты. Скрипт импорта, создающий экземпляры префабов, идентичен скрипту тарелок.
4.2. Пользовательские параметры для объектов
Теперь рассмотрим, как экспортировать однотипные объекты, у которых пользовательские параметры заданы не слою, а самому объекту. К таким объектам мы отнесем наших фанаток, купидонов, движущиеся платформы и т.д. Несмотря на однотипность, они обладают своими индивидуальными свойствами: скоростью движения, направлением и пр.
К примеру, фанатки различаются по цвету, они двигаются с разной скоростью на задаваемое расстояние. Они могут останавливаться, чтобы моргнуть, а при встрече с героем на выбор выдают определенные эмоций. Задаем эти параметры в Tiled для каждого объекта. “Свои параметры” для слоя, соответственно, остаются пустыми.

В Unity для фанаток созданы префабы, к которым присоединен скрипт GirlController, определяющий их поведение и реакцию на героя. Импорт будет аналогичен импорту тарелок, но просто создать экземпляры префаба в этом случае будет недостаточно. Нам нужно обратиться к скрипту GirlController и установить свойства, которые были заданы в Tiled индивидуально для каждой фанатки.
Выполняем экспорт в Unity и видим, что параметры, указанные в Tiled, были установлены переменным скрипта GirlController:


Повторяем описанную схему для объектов из других групп, и при экспорте в Unity получаем настроенные префабы большинства составляющих игры.
Описанный подход был использован нами для создания нашего платформера. Работа в связке Tiled Map Editor и Unity, именно в этой игре, ускорила процесс ее создания, позволив одновременно работать дизайнеру уровня в TME и программисту в Unity, не мешая друг другу. В проектах, подобных нашему, утилита Tiled2Unity может оказаться невероятно полезной, и, опираясь на статью, желающие могут применить любой из вариантов в своих игровых разработках.
Как это работает, расскажем на примере разработки нашего платформера “X-Drums”.
Двигаться будем по следующей схеме:
- Настройка экспорта Tiled2Unity
- Настройка столкновений в Tiled Map Editor
- Настройка параметров, которые поддерживает Tiled2Unity
- Настройка пользовательских параметров в Tiled Map Editor
- Пользовательские параметры для слоев (объектов)
- Пользовательские параметры для объектов
1. Настройка экспорта
Итак, у нас есть проект в Unity и есть карта, созданная в Tiled Map Editor. Запускаем Unity и импортируем Tiled2Unity.unitypackage.

В Tiled Map Editor вызываем окно редактирования команд:

Добавляем новую команду, в которой прописан путь до исполняемого файла Tiled2Unity.exe. Вместо %mapfile Tiled автоматически подставит путь к файлу карты. Последний аргумент этой команды — это путь к папке Tiled2Unity, которая должна была появиться в проекте после импорта.

Запускаем команду и в появившемся окне нажимаем большую кнопку.

В результате экспорта получаем префаб карты, который находится в папке Tiled2Unity. Размещаем этот префаб на сцене в Unity. Теперь при работе с картой в TME и ее экспорте, префаб и объект на сцене будут изменяться в соответствии с изменениями в TME.

Так мы настроили экспорт карты из Tiled в Unity и создали игровую среду.
Теперь займемся настройкой объектов на нашей карте.
2. Редактор столкновений
В первую очередь, определим элементы игрового пространства, которые будут препятствиями для героя. Это пол, стены, софиты на потолке, а также барабаны, выступающие платформами, по которым и будет прыгать герой.
Запускаем редактор столкновений в Tiled:

Выбираем нужный нам тайл, к примеру, часть барабана, и редактируем полигоны:

Аналогично редактируем другие нужные нам тайлы (пол, стены и т.д.). В результате, при экспорте Tiled2Unity автоматически создаст коллайдеры PolygonCollider2D, которые и будут выступать для героя препятствиями.


Однако другие объекты игры, с которыми может взаимодействовать герой, являются более сложными. Поведение тарелок, фанаток, нот и других элементов контролируется с помощью компонентов и скриптов. Для экспорта таких объектов необходимо указывать им дополнительные параметры в Tiled и затем обрабатывать их в Unity.
3. Параметры, которые поддерживает Tiled2Unity
Впрочем есть список параметров, которые мы можем использовать в Tiled без настройки их в Unity, поскольку Tiled2Unity уже сделал это за нас. Среди них:
| unity:layer unity:sortingLayerName unity:tag unity:sortingOrder unity:isTrigger unity:ignore |
The (physics) layer name in Unity The Name of the Sorting Layer in Unity The Name of the Tag in Unity The `sorting in layer` value in Unity Whether collider is a trigger or not Ignore layer (or parts of it) during import(value = [false|true|collision|visual]) |
Зададим нужные нам параметры для барабанных палочек, по которым будет прыгать герой:

При экспорте в Unity получаем такой результат:

Слою задан параметр OneWayPlatform, он используется для объектов, которые являются проницаемыми снизу.

4. Пользовательские параметры в Tiled
Обработку других параметров, назовем их “пользовательскими”, и экспорт объектов с такими параметрами, мы будем настраивать в Unity. Задавать их в Tiled можно как для слоев (объектов), так и для объектов. В разных случаях может бы��ь удобным первый или второй вариант. Рассмотрим, как это реализовать.
4.1. Пользовательские параметры для слоев (объектов)
Зададим пользовательские параметры для слоя. Этот вариант мы используем для однотипных объектов. В нашей игре такими являются тарелки и ноты. Их особенность в том, что они одинаково взаимодействуют с героем и не нужно их отличать друг от друга.
Создаем слой объектов в Tiled и размещаем на нем наши тарелки. Затем, задаем параметр AddObject для всего слоя.

Поле своих параметров для каждой тарелки остается пустым.

Теперь переходим в Unity, где для тарелок мы создали префаб и привязали к нему скрипт, определя��щий их поведение при прыжке героя — они падают и возвращаются в исходное положение.
Напишем код, который при импорте тарелок для каждого объекта из Tiled создаст экземпляр нашего префаба. Для этого создаем скрипт CustomTiledImporterForHiHats с классом, который наследует интерфейс Tiled2Unity.ICustomTiledImporter и атрибутом [Tiled2Unity.CustomTiledImporter].
Этот скрипт Tiled2Unity будет вызывать для каждого импортируемого из Tiled слоя и объекта. А обрабатываться, соответственно, будут те слои или объекты, у которых среди параметров есть параметр AddObject со значением “Hi-hat”.
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[Tiled2Unity.CustomTiledImporter]
class CustomTiledImporterForHiHats : Tiled2Unity.ICustomTiledImporter
{
public void HandleCustomProperties(GameObject gameObject, IDictionary<string, string> props)
{
if (!props.ContainsKey("AddObject"))
return;
if (props["AddObject"] == "Hi-hat")
{
//Загружаем префаб тарелок
string prefabPath = "Assets/8 - Prefabs/Hi-hat.prefab";
Object obj = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
if (obj == null)
return;
//Для каждого тайла, который будет загружен из Tiled,
//будет создан экземпляр префаба
//Сами тайлы будут удалены со сцены
List<GameObject> childrenToDestroy = new List<GameObject>();
//Проходим по списку объектов слоя
foreach (Transform child in gameObject.transform)
{
if (child.name == "TileObject")
{
//Добавляем тайл для последующего удаления
childrenToDestroy.Add(child.gameObject);
//Создаем экземпляр префаба, настраиваем его положение на сцене
GameObject objInstance = (GameObject)GameObject.Instantiate(obj);
objInstance.name = obj.name;
objInstance.transform.parent = gameObject.transform;
objInstance.transform.position = child.transform.position;
}
}
//Удаляем тайлы со сцены
childrenToDestroy.ForEach(child => GameObject.DestroyImmediate(child));
}
}
public void CustomizePrefab(GameObject prefab)
{
}
}
Скрипт готов, и мы можем экспортировать тарелки.

И вот так герой взаимодействует с ними.

Экспорт нот настроен точно так же как экспорт тарелок. Единственное отличие в том, что в игре есть несколько видов нот с разной стоимостью в зависимости от цвета. Поэтому для каждого типа нот со своим номиналом мы создали префаб в Unity и слой объектов в Tiled, указав ему в параметре AddObject тип ноты. Скрипт импорта, создающий экземпляры префабов, идентичен скрипту тарелок.
4.2. Пользовательские параметры для объектов
Теперь рассмотрим, как экспортировать однотипные объекты, у которых пользовательские параметры заданы не слою, а самому объекту. К таким объектам мы отнесем наших фанаток, купидонов, движущиеся платформы и т.д. Несмотря на однотипность, они обладают своими индивидуальными свойствами: скоростью движения, направлением и пр.
К примеру, фанатки различаются по цвету, они двигаются с разной скоростью на задаваемое расстояние. Они могут останавливаться, чтобы моргнуть, а при встрече с героем на выбор выдают определенные эмоций. Задаем эти параметры в Tiled для каждого объекта. “Свои параметры” для слоя, соответственно, остаются пустыми.

В Unity для фанаток созданы префабы, к которым присоединен скрипт GirlController, определяющий их поведение и реакцию на героя. Импорт будет аналогичен импорту тарелок, но просто создать экземпляры префаба в этом случае будет недостаточно. Нам нужно обратиться к скрипту GirlController и установить свойства, которые были заданы в Tiled индивидуально для каждой фанатки.
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[Tiled2Unity.CustomTiledImporter]
class CustomTiledImporterForGirls : Tiled2Unity.ICustomTiledImporter
{
public void HandleCustomProperties(GameObject gameObject, IDictionary<string, string> props)
{
if (!props.ContainsKey("GirlColor"))
return;
//Загружаем нужный префаб в зависимости от указанного в Tiled цвета
string prefabPath = "Assets/8 - Prefabs/Girls/Girl_" + props["GirlColor"] + ".prefab";
Object obj = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
//Создаем экземпляр префаба, настраиваем его положение на сцене
GameObject objInstance = (GameObject)Object.Instantiate(obj);
objInstance.name = obj.name;
objInstance.transform.parent = gameObject.transform.parent;
objInstance.transform.position = gameObject.transform.position;
objInstance.transform.localScale = gameObject.transform.localScale;
objInstance.transform.eulerAngles = gameObject.transform.eulerAngles;
//Обращаемся к скрипту, который определяет поведение фанатки
//Считываем параметры из Tiled и присваиваем переменным скрипта
var girlController = objInstance.GetComponent<GirlController>();
if (props.ContainsKey("OffsetRight"))
float.TryParse(props["OffsetRight"], out girlController.OffsetMax);
if (props.ContainsKey("OffsetLeft"))
float.TryParse(props["OffsetLeft"], out girlController.OffsetMin);
if (props.ContainsKey("Velocity"))
float.TryParse(props["Velocity"], out girlController.Velocity);
if (props.ContainsKey("Stop"))
float.TryParse(props["Stop"], out girlController.StopCount);
if (props.ContainsKey("Fatal"))
bool.TryParse(props["Fatal"], out girlController.Fatal);
if (props.ContainsKey("HeartType"))
{
string heartPrefabPath = "Assets/8 - Prefabs/Girls/" + props["HeartType"] + ".prefab";
Object heartObj = AssetDatabase.LoadAssetAtPath(heartPrefabPath, typeof(GameObject));
girlController.heartPrefab = heartObj;
}
//Удаляем тайл со сцены
Object.DestroyImmediate(gameObject);
}
public void CustomizePrefab(GameObject prefab)
{
}
}
Выполняем экспорт в Unity и видим, что параметры, указанные в Tiled, были установлены переменным скрипта GirlController:


Повторяем описанную схему для объектов из других групп, и при экспорте в Unity получаем настроенные префабы большинства составляющих игры.
Описанный подход был использован нами для создания нашего платформера. Работа в связке Tiled Map Editor и Unity, именно в этой игре, ускорила процесс ее создания, позволив одновременно работать дизайнеру уровня в TME и программисту в Unity, не мешая друг другу. В проектах, подобных нашему, утилита Tiled2Unity может оказаться невероятно полезной, и, опираясь на статью, желающие могут применить любой из вариантов в своих игровых разработках.
