Игра-головоломка NeoAngle. Работа с уровнями в Unity

ec29a327056e49929da86e428eb359f8.png

Всем доброго времени суток! Я бы хотел вам рассказать историю своей новой игры-головоломки NeoAngle, а также поделиться опытом импортирования, хранения и генерации уровней в Unity.

Начну с краткой предыстории, которая началась еще 5 лет назад, когда я решился заняться геймдевом, впервые познакомившись с языком программирования action script 3.0 (для разработки flash-игр) в университете.

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

Таким образом, затратив неделю на разработку в одиночку, была выпущена моя первая flash-игра SeaQuest.

686e213d47f442cda61613acbede3ef7.PNG

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

09cb5f680722477eb90995a907bf43b0.jpg
Результат под названием Stone Quest

На этом линейка логических игр завершилась и была успешно мной позабыта.

Далее последовал обещанный обвал флэш индустрии, который перекинул меня в unity разработку для мобильных. И вот, в декабре 2016 года, совершенно случайно мне в голову вернулась мысль о треугольно-ориентированных головоломках. Особенно подтолкнуло к разработке то, что геймплей отлично подходит под тачскрин. Было решено использовать механику предыдущей игры, но с другой стилизацией.

Вот такая предыстория, которая привела к активной полуторамесячной разработке. Большая часть работы, как ни странно, ушла на геймдизайн. Из предыдущей версии почти все уровни мне показались недостаточно интересными, хотя возможности геймплея имеют гораздо больший потенциал. В следствие чего разработка началась с редактора уровней, который я написал за вечер на старом добром флэше, с возможностью тестирования написанных уровней и их экспорта/импорта в xml.

Результат работы в редакторе продемонстрирован ниже:

ad497e1fccf740e886db98f0b1a62beb.gif

Прежде чем перейти к работе с Unity, мне необходимо было убедиться в том, что я смогу предоставить достаточное количество уровней для мобильной игры, которая требует разнообразный контент. Поэтому первые полторы недели я даже не открывал Unity, а работал в своем редакторе, параллельно занимаясь графикой. К слову, был выбран набирающий популярность ретро-стиль synthwave 80-ых. Он достаточно прост в исполнении, являясь при этом очень привлекательным.

3180657424bb42e2a5f0fd9ec7b527db.png

Таким образом, создав допустимый набор уровней, я приступил к их портированию в Unity, продолжив тратить часть времени на доработку и создание новых.

В связи с этим, возникли следующие вопросы: каким образом импортировать, хранить и генерировать уровни в Unity из xml файла?

Найденных вариантов решения было три:

1. При старте игры вычитывать xml файл и каждый раз динамически создавать уровни на runtime.
2. В edit mode сгенерировать уровни и создать на каждый по сцене.
3. В edit mode сгенерировать уровни и создать для каждого префаб.

Очевидно, что первый вариант не самый лучший, т.к. все уровни заранее подготовлены и нету смысла их каждый раз заново создавать. Второй вариант больше подходит для более сложных и масштабных проектов, где каждый уровень имеет свою логику, интерфейс, структуру и т.п. В моем случае пришлось бы дублировать интерфейсы и ключевые объекты в каждую сцену с уровнем и при каждом изменении ui нужно было бы обновлять все сцены. Остается последний третий вариант, который как раз очень удачно подошел. О его реализации я и продолжу повествование.

Для работы с объектами в edit mode добавим кастомную панель в редакторе Unity. Для этого создаем класс наследуемый от EditorWindow в папке Assets/Editor и добавляем туда следующий метод:

[MenuItem ("Window/Level Loader")] // Level Loader - название панели в списке Window. 
public static void ShowWindow () {
    EditorWindow.GetWindow(typeof(LevelLoader)); // LevelLoader - имя созданного класса
}

Сразу же проверим, что панель создана в Window → Level Loader:

0850c8de96274f09aee9da914009aa1d.png

Далее, в методе OnGUI можно начинать добавлять кнопки и поля для нашего окна.

Базовые примеры:

void OnGUI() {
    GUILayout.Label ("Custom Label", EditorStyles.boldLabel); // добавление заголовка

    // создание поля для выбора GameObject
    GameObject customGO = EditorGUILayout.ObjectField(customGO, typeof(GameObject), true) as GameObject; 

    int customInt = EditorGUILayout.IntField(customInt); // создание поля для ввода int значения

    EditorGUILayout.Space(); // добавление вертикального отступа

    if (GUILayout.Button("Custom Button")) // добавление кнопки с обработчиком нажатия
    {
        ButtonHandler();
    }
}

Больше информации по компонентам можно найти в официальной документации. А я продолжу описание моего Level Loader«a, продемонстрировав принцип работы ниже:

48120f456a664d93acfa7616658b91ba.gif

Сперва, мы вычитываем уровни из xml файла, путем нажатия на Read Levels, после этого создается выпадающий список с возможностью выбора уровня и появляются дополнительные контролы, которые позволяют сгенерировать уровень на сцене, создать префаб выбранного уровня, пересоздать префабы всех уровней, показать/скрыть номера полей (для тестирования отрисовки и отслеживания ошибок).

Для создания объектов на сцене в edit mode используется стандартная функция Instantiate, а для удаления DestroyImmediate.

Какое-то время я создавал префабы уровней вручную, перетягивая их со сцены в папку Resources. Однако, это быстро мне надоело и я полез в интернет за информацией о том, как создавать префабы в edit mode программными средствами. Ниже конструкция, позволяющая это сделать:

private void CreateLevelPrefab() {
    GameObject levelGO = GameObject.FindGameObjectWithTag("Level").gameObject; 
    // игровой объект Level содержит сгенерированный на сцене уровень

    Object levelPrefab = EditorUtility.CreateEmptyPrefab("Assets/Resources/"+levelGO.name+".prefab");
    EditorUtility.ReplacePrefab(levelGO, levelPrefab, ReplacePrefabOptions.ConnectToPrefab);
}

Далее, в режиме игры уровни добавляются на сцену следующим образом:
GameObject levelGO = Instantiate (Resources.Load ("Level"+levelNum) as GameObject);

Так, этапы добавления уровней получились следующие:
  • Создание/редактирование уровня во flash-редакторе с последующим экспортом в xml
  • Считывание xml уровня в unity
  • Генерация уровня на сцене в edit mode
  • Создание/обновление префаба уровня в папке Resources

На этом всё. Для меня это был первый опыт работы с объектами в режиме редактирования. Буду рад ознакомиться с вашими идеями по поводу реализации редактора уровней прямо в Unity, миновав Flash.

Спасибо за внимание! Оценить игру можно в Google Play по запросу NeoAngle.

Комментарии (0)

© Habrahabr.ru