В Unity 2018.3 появилась поддержка изометрических тайловых карт, очень напоминающая поддержку тайловых карт шестиугольников, которая была добавлена в версии 2018.2. Новые функции Tilemap позволяют быстро и эффективно создавать 2D-окружения на основе изометрических и шестиугольных сеток, которые использовались во многих классических играх, в том числе в первых частях Diablo и Fallout, Civilization, Age of Empires, и многих других.
Обе системы построены на основе уже существовавшей системы Tilemap, появившейся в Unity 2017.2, и сегодня работать с ними так же просто! Кроме того, они имеют нативную интеграцию с Editor. В дальнейших версиях Unity они могут быть перенесены в package manager.
Если вам интересно поэкспериментировать с этими системами, мы создали заранее подготовленный проект Isometric Starter Kit с анимированным персонажем и несколькими тайлсетами окружений. Скачать его можно здесь.
Параметры проекта для Isometric Tilemap
Прежде чем мы начнём работать с Tilemap, важно правильно настроить проект. Isometric Tilemap работает с двухмерными спрайтами и использует правильную сортировку рендеринга для создания иллюзии изометрической карты с видом сверху. Нам нужно сделать так, чтобы тайлы, находящиеся дальше от зрителя, отрисовывались первыми, а более близкие — поверх них.
Для настройки порядка отрисовки 2D-объектов на экране можно воспользоваться функцией Unity под названием Custom Axis Sort. Этот параметр можно задавать или для камеры (в настоящий момент такой способ является стандартным для Scriptable Render Pipelines, в том числе для LWRP и HDRP), или глобально, на уровне проекта.
Чтобы задать Custom Axis Sort на уровне проекта, перейдём в Edit > Project Settings > Graphics. В разделе Camera Settings вы увидите раскрывающееся меню Transparency Sort Mode, а также параметры значений X, Y Z для Transparency Sort Axis.
По умолчанию в Transparency Sort Axis для осей XYZ заданы значения (0, 0, 1). Однако все наши 2D-тайлы на самом деле находятся на одной плоскости Z. Поэтому для определения того, какие тайлы находятся впереди или позади, нужно использовать не глубину, а высоту. Тайлы, расположенные выше на экране, будут отсортированы под более низкие. Чтобы отсортировать тайлы по высоте, изменим значение Transparency Sort Mode на Custom и зададим для Transparency Sort Axis значения (0, 1, 0).
Чтобы подробнее узнать, как это работает, можете прочитать соответствующую страницу о 2D-сортировке в документации Unity.
В некоторых случаях может также понадобиться изменить для Transparency Sort Axis значение Z. Подробнее об этом мы расскажем ниже.
Типы тайловых карт
Система Tilemap состоит из нескольких взаимодействующих компонентов. Первые два — это игровые объекты Grid и Tilemap. Для создания Grid достаточно нажать правой клавишей мыши в любом месте Hierarchy, перейти к пункту 2D Object и выбрать тип Tilemap, который вы хотите использовать. По умолчанию каждая новая сетка Grid создаётся с одним дочерним игровым объектом Tilemap соответствующего типа. На данный момент существуют следующие типы Tilemap:
Tilemap — создаёт прямоугольные Grid и Tilemap. Пример использования этого Tilemap можно увидеть в 2D Game Kit движка Unity.
Hexagonal Point Top Tilemap — создаёт Grid и Tilemap из шестиугольников, в которых одна из вершин каждого шестиугольника направлена вверх.
Hexagonal Flat Top Tilemap — ещё один тип Grid шестиугольников, в котором вверху шестиугольника находится грань, параллельная верхнему краю экрана.
Два последних типа, Isometric и Isometric Z as Y, создают две разные реализации изометрической сетки. Разница между ними проявляется при симуляции различных уровней высот тайлов, например, когда на изометрическом уровне есть высокая платформа.
Если вы хотите создавать отдельные игровые объекты Tilemap для каждого уровня высот тайлов, то лучше использовать обычный тип Isometric Tilemap. Он упрощает процесс создания автоматических форм коллизий, но обладает меньшей гибкостью при работе с перепадами высот между тайлами, потому что все тайлы на одном слое должны находиться на одной «плоскости».
В случае Isometric Z as Y Tilemap значение позиции по Z каждого тайла работает в сочетании с параметром Transparency Axis Sort, делая так, что тайлы кажутся положенными друг на друга. При рисовании на Z as Y Tilemap мы динамически изменяем параметр Z кисти для переключения между разными высотами. Для правильного рендеринга Z as Y Tilemap требуется дополнительное значение Z в Transparency Sort Axis с режимом Custom.
Примечание: показанные на скриншотах ассеты взяты из тайлсета Temple проекта Isometric Starter Kit. Они совершенно бесплатны, поэтому можно пользоваться ими для создания собственных окружений!
Воспринимайте Grid как «мольберт», на котором располагаются все игровые объекты Tilemap. А они, в свою очередь, по сути являются холстом, на котором мы будем рисовать тайлы. Чтобы начать рисование на Tilemap, нам также понадобятся кисть и палитра. Все тайловые ассеты находятся на Tile Palette, из которой их можно выбирать при помощи инструмента кисти и начинать рисование.
Для создания Tile Palette выберите Window > 2D > Tile Palette. В левом верхнем раскрывающемся меню выберите «Create New Palette». Убедитесь, что выбран соответствующий тип сетки. В примере я буду использовать обычный Isometric Tilemap, а также ассеты из проекта Isometric Starter Kit. В качестве размера ячейки палитры (cell size) укажем Manual, чтобы иметь возможность изменять размеры изометрических тайлов. В данном случае я знаю, что размеры моих тайлов соответствуют сетке с размером ячейки 1 по X и 0.5 по Y; однако они зависят от разрешения, выбранных при импорте значений pixels per unit и размеров ассетов — по сути, от изометрического угла, на который повёрнуты тайлы.
Примечание об импорте ассетов
Возможно, вы не знаете, какие параметры импорта и размер тайловой карты лучше подойдут вашим ассетам. Существует общее правило, которому можно следовать: сначала нужно посмотреть на разрешение тайлов. Обычно изометрические тайлы-блоки больше по высоте, чем по ширине; «плоские» тайлы (которые больше походят на плоскость, чем на куб) больше по ширине, чем по высоте. Однако ширина между ними всегда будет одинаковой. Поэтому если вы хотите, чтобы тайлы занимали ровно одну единицу измерения Unity, то укажите для Pixels Per Unitв параметрах импорта тайлов значение, равное их ширине в пикселях. В некоторых случаях это значение придется изменить, обычно в сторону уменьшения (или увеличения разрешения ассетов); это может оказаться полезным, если вы хотите воссоздать эффект, при котором некоторые тайлы кажутся занимающими больше, чем одну ячейку сетки, и накладываются на соседние тайлы.
Чтобы определить правильное значение сетки по Y для тайлов, возьмите высоту основания (или вершины) одного тайла, и поделите его на ширину. Это даст вам значение Y относительно X, с учётом того, что X равен 1. Давайте рассмотрим примеры:
В пиксель-артных ассетах, которые мы используем для этого проекта, все тайлы оснований имеют высоту 32 пикселя и ширину 64 пикселя. Поэтому размер сетки по Y будет равен 0.5. Второй блок на изображении взят из пакета ассетов Golden Skull Studios; посмотреть его можно здесь. Тайл примера был уменьшен, но исходные ассеты имеют ширину 128 пикселей. Основание тайла примерно равно 66 пикселям, что даёт размер сетки Y, равный 66/128, то есть приблизительно 0.515 единицы.
Базовый процесс работы с Tilemap
Определившись с правильными размерами Grid, добавим в нашу палитру несколько тайлов. Просто возьмите один из спрайтов тайлов и перетащите его в окно Tile Palette. Так будет создан Tile Asset. Он содержит информацию о самом тайле, например, используемые им спрайты, оттенок и тип генерируемого коллайдера. Если вам нужно посмотреть подробную информацию о тайле палитры, выберите инструмент Select (S) в верхней части окна Tile Palette и нажмите на этот тайл. Заметьте, что Inspector можно увидеть, на какой Tile asset он ссылается.
Для рисования новым Tile по Tilemap выберите инструмент Brush (B) и нажмите на Tile в Palette. После этого вы сможете рисовать выбранным тайлом в окне сцены. Есть и другие инструменты рисования, например, Eraser (D), Box Fill (U), Flood Fill (G) и Tile Picker (I).
Иногда требуется изменить расположение тайлов на самой палитре. Сразу под панелью инструментов есть кнопка Edit. Если нажать на неё, то включится режим редактирования палитры, в котором инструменты воздействуют на саму Tile Palette. Не забудьте выйти из этого режима после внесения нужных изменений.
Режимы Tilemap Renderer
В некоторых случаях тайлы разных типов могут сортироваться неправильно, несмотря на то, что находятся на одной Tilemap, как на этом примере:
Это определяется параметром Mode компонента Tilemap Renderer. По умолчанию Mode имеет значение Chunk.
Режим Chunk эффективен в снижении потребления ресурсов ассетом Tilemap. Вместо рендеринга каждого тайла по отдельности он рендерит их за один проход как большой блок. Однако этот режим имеет два основных недостатка. Первый — он не поддерживает динамическую сортировку с другими 2D-объектами в сцене. Это значит, что если Tilemap находится в режиме Chunk, то она не сможет динамически сортироваться перед или за другими объектами, например, персонажами — одновременно будет виден только тот или другой, и это зависит от параметра Order in Layer. Однако он всё равно чрезвычайно эффективен для оптимизации игры и может использоваться для пакетного рендеринга больших областей рельефа.
Однако это не избавляет нас от проблемы неверной сортировки разных тайлов. Для пакетного рендеринга тайлов, взятых из двух или более различных спрайтов (например, текстур), спрайты должны быть объединены в один ассет Sprite Atlas.
Чтобы создать Sprite Atlas, выберите Assets > Create > Sprite Atlas. В параметрах Sprite Atlas есть список Objects for Packing. Просто перетащите в него все тайлы, которые нужно рендерить пакетно, и укажите подходящие параметры импорта, обычно совпадающие с параметрами отдельных спрайтов.
После этого тайлы будут сортироваться правильно; но они будут видимы только в режиме Play или во время выполнения игры.
Поэтому в процессе редактирования лучше выбрать для Tilemap Renderer режим Individual. В этом режиме каждый спрайт будет сортироваться по отдельности; это значит, что они будут правильно рендериться даже вне режима Play, что очень полезно при редактировании уровня. Завершив создание структуры уровня, можно в любой момент снова переключить режим Tilemap Renderer на Chunk.
Режим рендеринга Individual также полезен, когда нужно добавлять такие объекты, как деревья, предметы и более высокие участки земли, которые должны динамически сортироваться с персонажами или друг с другом. В этом посте мы включим для всех Tilemap режим Individual.
Использование нескольких Tilemap
Иногда требуется использовать несколько Tilemap на одной Grid. В случае изометрических и шестиугольных Tilemap, полезно иметь возможность добавления на уровень предмета, выровненного по сетке или тайлов, которые кажутся выше, чем первый слой.
Чтобы подключить к сетке ещё один Tilemap, нажмите правой клавишей мыши на игровой объект Grid и создайте новый Tilemap соответствующего типа.
Чтобы перейти к рисованию на новом Tilemap, вернитесь в окно Tile Palette и измените Active Tilemap под основной панелью инструментов.
Добавление поднятых вверх областей
Существует два основных способа добавления на уровни поднятых вверх областей. Выбор подходящего обычно зависит от типа выбранного Tilemap. Мы рассмотрим каждый из случаев.
Кроме того, мы подготовили краткое видео по этой теме, в котором на примере обычной Isometric Tilemap демонстрируются эти подходы, а также добавление тайлам областей коллизий. Посмотрите видео, если хотите вкратце понять оба этих способа:
Использование обычной Isometric Tilemap
Для обычных Isometric Tilemap можно просто создать новый Tilemap у той же Grid и присвоить Order in Layer более высокое значение. Затем можно изменить параметр Tile Anchor, чтобы новый слой был привязан к более высокой точке в той же сетке.
У моей Tilemap нижнего уровня для X и Y в Tile Anchor установлено (0, 0). Я хочу, чтобы новый слой отрисовывался на одну единицу выше, поэтому я изменю точку привязки нового Tilemap на (1, 1). Также я присвою Order in Layer значение 1 — на единицу больше, чем уровень основания.
Теперь можно сменить активный Tilemap на имеющий второй уровень высоты и начать рисование.
Использование Z as Y Isometric Tilemap
Иногда бывает полезно имитировать разные высоты при помощи одной Tilemap. В таком слуае можно использовать Z as Y Isometric Tilemap и Grid.
В случае Z as Y Tilemap значение Z каждого тайла имеет дополнительное влияние на порядок рендеринга тайлов. Мы можем менять значение Z тайлов при их рисовании при помощи параметра Z Position кисти в нижней части Tile Palette (а также при помощи горячих клавиш "+" и "-"):
Однако для того, чтобы значение Z влияло правильно и тайлы сортировались верно, нужно вернуться к значению Custom Axis Sort и добавить влияние Z. Используемое здесь число непосредственно связано с тем, как Unity преобразовывает позиции ячеек изометрической сетки в значения в мировом пространстве.
Например сетка с размерами по XYZ of (1, 0.5, 1) — стандартная для изометрии — будет иметь значение сортировки по оси Z, равное -0.26. Если вам интересно, как вычислено это число, или вы используете сетку с другим размером ячейки, то продолжайте чтение, чтобы узнать, как найти правильное значение Z для вашего случая.
Задав правильное значение Custom Axis Sort, можно начинать рисовать тайлы, имеющие различные значения Z. Также можно настроить инкременты, с которыми значение Z перемещает поднятые тайлы вверх или вниз, изменив размер Z сетки Grid, по умолчанию равный 1.
Вычисление значения Z
Существует общая формула, которую можно использовать для определения значения Z сортировки по оси. Сначала берём размер Y сетки. Если вы пока не определились с размером Y, посмотрите выше примечание об импорте ассетов. Умножьте это значение на -0.5, и вычтите ещё 0.01.
Согласно этой формуле, сетка, имеющая размер (1, 0.5, 1), даст нам значение сортировки по Z, равное -0.26. При таком значении сортировки по ости тайлы любой сетки (1, 0.5, 1) будут сортироваться правильно.
Если вы хотите больше узнать об этом значении и о вычислениях, то изучите документацию. В ней подробно объяснена работа 2D-рендереров и то, что происходит при преобразовании изометрических ячеек в значения мирового пространства.
Добавление коллизий
Теперь, когда мы разместили часть тайлов над другими, при помощи коллизий можно контролировать области, в которые способен добраться игрок, и переходы между ними.
Существует множество способов добавления коллизий, но в нашем случае требуется, чтобы игрок поднимался и опускался по склону, поэтому не так очевидно, у каких объектов должны быть коллайдеры. Мы можем задать коллизии вручную при помощи дополнительной Tilemap.
В этом проекте мы создали несколько спрайтов, соответствующих различным формам, которые будут задавать области коллизий. Мы можем нарисовать эти формы на третьем Tilemap в тех местах, где игрок проходить не может. Например, мы хотим, чтобы игрок умел подниматься на скалу только по склону, а не забирался на неё напрямик.
Также мы можем добавить в Tilemap Renderer уникальный материал, чтобы придать тайлам другой оттенок и отличать их от остальной части уровня.
Разместив тайлы коллизий, можно добавить в Tilemap коллизий компонент Tilemap Collider. При этом для каждого отдельного тайла автоматически создадутся коллайдеры, определяемые формой спрайта.
Для оптимизации производительности можно также добавить компонент Composite Collider 2D и поставить у Tilemap Collider флажок Used by Composite. Это объединит все отдельные коллайдеры в одну большую фигуру.
Добавление предметов
Добавление предметов на уровень выполняется довольно просто. Можно или вручную размещать спрайты предметов в любую нужную точку сцены, или прикреплять предметы к Tilemap Grid, превращая их в отдельные тайлы. Сами выбирайте, какое решение больше подойдёт вам.
В этом проекте мы вручную разместили на уровне несколько деревьев. Деревья и персонаж имеют одинаковый Order in Layer, что позволяет динамически сортировать персонажа перед и за деревьями.
При помощи коллайдера можно задать точку, в которой игрок может пройти возле дерева. Это также можно сделать несколькими способами.
Первый показан в видео — достаточно прикрепить к объекту дочерний коллайдер и изменить его форму нужным образом.
Второй способ — задание Custom Physics Shape для объекта в Sprite Editor. Чтобы открыть Sprite Editor, выберите спрайт объекта и найдите в Inspector кнопку Sprite Editor. В левом верхнем раскрывающемся меню переключитесь в редактор Custom Physics Shape. Здесь вы сможете создавать полигональные фигуры, определеющие границы коллайдера. Задав физическую форму, можно прикрепить компонент Polygon Collider к объекту, и он будет соответствовать этой форме.
Если вы используете предметы как тайлы в Tilemap, то можете также воспользоваться коллайдером Grid. Выберите Tile Asset, соответствующий тайлу предмета (если вы не помните, где его найти, то см. раздел «Базовый процесс работы с Tilemap»). Вы увидите меню Collider Type. По умолчанию в качестве типа задан спрайт, то есть автоматически сгенерированный коллайдер будет использовать Physics Shape, о котором мы говорили выше. Если в качестве типа задана сетка. то он всегда будет точно соответствовать форме ячейки сетки, к которой прикреплён предмет. Возможно, это и не самый точный способ реализации коллайдеров, но для некоторых видов игр он может оказаться полезным.
Чтобы использовать для этих тайлов коллайдеры, выберите Tilemap с предметами и добавьте компонент Tilemap Collider.
Использование Rule Tiles
Rule Tiles чрезвычайно полезны для автоматизации процесса рисования тайлами. Rule Tile работает как обычный тайл, но имеет дополнительный список параметров тайлинга. При помощи этих параметров (правил) тайл может автоматически выбирать, какой спрайт нужно отрисовывать в зависимости от соседних тайлов.
Rule Tiles полезны, когда вы не хотите подбирать вручную тайлы с разным поворотом, например, при создании скалы или платформы. Также их можно использовать для рандомизации между разными вариациями одного тайла, чтобы избежать повторяющихся паттернов, и даже для создания анимированных тайлов.
Изометрические и шестиугольные Rule Tiles доступны из репозитория 2D Extras Unity на GitHub. В нём также есть множество других полезных ассетов для системы Tilemap, которые стоит изучить.
Мы добавили в проект Isometric Starter Kit тайлы Rule Tiles для каждого из тайлсетов. Вот некоторые примеры из тайлов проекта, с которыми можно поэкспериментировать:
Дальнейшая работа
Теперь, когда вы узнали об устройстве изометрических тайловых карт в Unity, скачайте проект Isometric Starter kit и попробуйте поработать с ними самостоятельно! Если вы программист, то у вас есть возможность взаимодействовать с Tilemap через скрипты, можете ею воспользоваться.
Например, посмотрев это видео, вы сможете узнать, как реализовать простой контроллер персонажа, совместимый с Isometric Tilemap:
Графика этого проекта была создана для Unity художницей @castpixel; другие её работы можно посмотреть здесь. Если вы хотите больше узнать о создании 2D-игр на Unity, то вам стоит изучить отличные курсы с веб-сайта Learn. Если вы ищете дополнительные ресурсы для экспериментов с тайловыми картами, то загляните в Unity Asset Store.
Впервые создаёте уровни при помощи Tilemap? Изучите построение двухмерных миров в этом туториале для новичков на Unity Learn.
Автор: PatientZero