Как я делал редактор уровней для 2.5D игры в Unity

Мини видео про возможности редактора :)

Была идея сделать редактор уровней, чтобы ускорить создание контента для игры и в будущем дать возможность создавать уровни игрокам.

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

Пример как выглядит уровень в Unity Editor
Пример как выглядит уровень в Unity Editor

Платформы и стены: Я заранее сделал части моделей определенного размера под каждый биом и вариации углов между ними (от 5 до 45 градусов)

Мой лего-конструктор дома
Мой лего-конструктор дома

Игровые объекты: Есть множество объектов, которые должны быть на поверхности платформы или стены.

Часть игровых объектов (слево-направо: табличка, мина, указатель, кнопка для куба, обычная кнопка, знак опасности, куб, отталкивающая платформа)
Часть игровых объектов (слево-направо: табличка, мина, указатель, кнопка для куба, обычная кнопка, знак опасности, куб, отталкивающая платформа)

Ещё любой уровень должен обязательно иметь объект финиша.

Флажок с вентилятором = финиш
Флажок с вентилятором = финиш

Что вкратце сделал

  • Менеджер объектов на сцене
  • Undo/Redo базовых операций
  • Разделить игровые объекты и объекты редактора уровня
  • Генератор иконок
  • Выделение объектов через клик либо зону
  • Перемещение, вращение, изменение размера объектов через Runtime Transfrom Handles пакет
  • Контекст меню для любого объекта (чтобы настраивать соотв. параметры для уникальных объектов кроме позиции, поворота и размера)
  • Сохранение и загрузка уровня через файл

Менеджер объектов сцены

Начал с него. Менеджер пригодится, чтобы в будущем быстро искать объекты в сцене через словарь, а также для сохранения и загрузки уровня, не ломая связи между объектами. Любой созданный объект имеет InstanceId от Unity, но он непостоянный между сессиями и связи между объектами ломаются после загрузки уровня (например кнопка, которая активирует лифт). В моем менеджере у меня есть свой id, который растет с каждым новым созданным объектом на +1, словарь {id, GameObject} и все операции создания / удаления объектов я делаю через него. При создании объекта я добавляю в его имя постфикс id{x}, чтобы затем получить его обратно из имени.

Undo/Redo

Чтобы была возможность делать Undo/Redo, я добавил интерфейс ICommand и написал отдельный класс с историей для них, возможностью группировать несколько команд в один шаг для истории. Ниже прикрепляю мою базу для работы:

Undo/Redo лучше реализовать сразу, чтобы потом не рефакторить код в команды + можно по ходу разработки это все тестировать и сразу править баги. Реализовал команды создания, удаления, перемещения объектов. Решение сделать Undo/Redo оказалось довольно удобным для пользователей, но с точки зрения разработки я довольно много времени потратил на тестирование каждой новой команды.

Объекты для редактора уровня

Пришлось разграничить объекты в проекте под редактор и игру. У меня все объекты выделяются через рейкаст систему в Unity, поэтому нужен отдельно коллайдер для каждого, что можно выделить в редакторе. Я сделал префаб-варианты игровых объектов с их настройкой под редактор соответственно.

Чтобы хоть как-то разместить объект в сцене, я решил сделать палитру объектов в UI.

Палитра объектов для размещения
Палитра объектов для размещения

Для этого нужно было сделать конфиги (ScriptableObject) под каждый объект, где есть иконка, ссылки на игровой и редактора объекты (загружаю я их через Addressables). Чтобы не умереть от рутины, 200+ конфигов объектов создал через код, в том числе связка иконок в будущем через сравнение имен конфига и иконки.

Генератор иконок

Для иконок нужно было сделать генератор. В интернете не нашел подходящий, но, изучив бесплатные, сделал свой (пока только для URP). В моем решении ты сам выставляешь объекты в сцене и картинка получается с прозрачным фоном + сглаживание работает.

Выделение объектов

Необходимо как-то двигать, вращать объекты, но для начала их нужно выбрать. Сделал менеджер выделения объектов. Через него можно получить информацию о них + накидывается обводка. Для обводки объектов использовал этот ассет (работает через Post Processing и добавляет обводку при помощи Rendering Layer Mask, что довольно удобно)

Runtime Transfrom Handles

Добавил гизму, чтобы двигать, вращать и менять размер объектам. Использовал этот инструмент (но пришлось адаптировать и мелкие баги поправить)

визуально так выглядит
визуально так выглядит

Контекст меню объекта

Контекст меню с элементами для объекта "Триггер зона игрока"
Контекст меню с элементами для объекта "Триггер зона игрока"

Тут можно настроить любой объект и дописать отдельные контекст элементы для каждого при необходимости. На их реализацию ушло довольно немало времени, пришлось сделать свои UI элементы ввода с обратными событиями (Vector2, Vector3, float) + на каждый уникальный объект (мина, кнопка и т.п.) свой скрипт под контекст элемент и обработчик.

В целом когда продумывал редактор, то вдохновлялся Unity инспектором.

Сохранение и загрузка уровня

Для сохранения и загрузки я использую менеджер объектов. При сохранении он пробегается по всем объектам уровня и записывает данные каждого в такой класс:

public class CustomLevelObject { public int InstanceId; public SerializableVector3 Position; public SerializableQuaternion Rotation; public SerializableVector3 Scale; public Dictionary<ObjectDataKey, object> AdditionalData; }

Где AdditionalData это дополнительные параметры для уникальных объектов по типу мина, лифт и другие. InstanceId мне нужен для связки объектов между собой (кнопка-лифт).

Все данные уровня сохраняю в json формате, пока не знаю как лучше, но весомых проблем в этом не обнаружил.

Было интересно реализовать сохранение и загрузку событий для кнопок (UnityEvent), для этого пришлось сделать отдельный контекст элемент в UI +- как в Unity инспекторе. Пришлось использовать рефлексию, чтобы взять нужный метод по названию класса для добавления его в UnityEvent.

Итого

На реализацию альфа-версии редактора уровня у меня ушло 1.5 месяца, что довольно немало.

Планирую в будущем отполировать редактор и вшить в игру с поддержкой Steam Workshop. Сейчас же там только английская локализация, есть пару багов, но в целом уже достаточно, чтобы делать уровни (пока что я конвертирую из файла в префаб и мелочи правлю в Unity).

Если интересно дальше следить за небольшими новостями по разработке, приглашаю в мой ТГ - там пишу о разработке и билд редактора будет.

Делал редактор для игры Wheel Balance, демо версия уже доступна. Релиз 25го июня.

Надеюсь этот материал будет кому-то полезен!

5
1
1 комментарий