Как сделать сцену в юнити 2д

Добавил пользователь Алексей Ф.
Обновлено: 10.09.2024

Любая игра разбита на несколько уровней. Это значительно увеличивает производительность игры и упрощает ее создание.

  1. Создай первый уровень и сохрани его с уникальным именем, выбрав в главном меню File -> Save Scene As…
  2. Добавь в проект новый уровень выбрав в главном меню File -> New Scene. Когда уровень будет готов, сохрани его (File -> Save Scene As…).
  3. Открой уровень на панели Project, который будет открываться первым при запуске игры. Выбери в главном меню File -> Build Settings…. Нажми кнопку Add Open Scenes, чтобы текущий уровень добавился в список Scenes In Build. Повтори эти операции с другими уровнями, чтобы все они добавились в список Scenes In Build.
  4. Осталось только написать простой скрипт, который поможет тебе перемещать игрока между уровнями (сценами). Для этого тебе необходимо разобраться с триггерами.

Триггеры

Разберем работу триггеров на прототипе, который мы подготовили:

Задача: сделать переход из одной сцены в другую и обратно, когда Игрок подходит к двери. Триггеры подойдут замечательно.

Триггер — это зона срабатывания определенных действий, когда объект входит в эту зону, находится в ней или выходит за ее пределы. Он часто используется для автоматического открывания дверей, загрузки уровней, отображения обучающих игровых подсказок, игровых роликов… Используй свою фантазию!

Для обработки триггеров скрипт получает события OnTriggerEnter, OnTriggerStay и OnTriggerExit. Работа с ними полностью аналогична работе с событиями Start и Update. Событие OnTriggerEnter будет посылаться, когда объект только вошел в зону триггера. Это то, что нам нужно, но для начала создадим сами объекты с триггерами.

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

  1. Создай пустой объект GameObject -> Create Empty.
  2. Добавь к созданному объекту один из компонентов Collider (Box Collider, Sphere Collider, Capsule Collider, Mesh Collider), расположенный в меню Component -> Physics.
  3. Размести триггер прямо перед дверью.
  4. В настройках добавленного компонента включи параметр Is Trigger.
  5. Повтори это во второй сцене.

Теперь тебе понадобится этот скрипт: OnTriggerSceneLoader.7z. Разберем как он работает.

Размести этот скрипт на триггерах. В сцене внутри Башни укажи SceneName, который соответствует названию сцены снаружи Башни. И наоборот.

В этом уроке я покажу вам, как использовать новые 2D-инструменты, включенные в Unity, для создания 2D-игры.

1. Обзор приложения


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

В этом проекте вы изучите следующие аспекты разработки Unity:

  • настройка 2D проекта в Unity
  • знакомство с интерфейсом Unity
  • создание префаба
  • прикрепление скриптов к игровым объектам
  • работа с физическими столкновениями
  • используя таймеры

2. Создайте новый проект Unity


3. Настройки сборки


Unity может создавать приложения для iOS, Android, BlackBerry и Windows Phone 8, что прекрасно, если вы планируете создать мобильную игру для нескольких платформ.

4. Устройства

Поскольку мы собираемся создать 2D-игру, первое, что нам нужно сделать после выбора платформы, на которую мы нацеливаемся, — это выбрать размер обложки, которую мы будем использовать в игре.

  • iPad без сетчатки: 1024 x 768 пикселей
  • iPad с сетчаткой : 2048px x 1536px
  • 3,5 «iPhone / iPod Touch без сетчатки: 320px x 480px
  • 3,5 «iPhone / iPod с сетчаткой : 960px x 640px
  • 4 «iPhone / iPod Touch: 1136 пикселей x 640 пикселей

Поскольку Android является открытой платформой, существует множество различных устройств, разрешений экрана и плотности пикселей. Некоторые из наиболее распространенных из них перечислены ниже.

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854 x 480 пикселей, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

А для вдов телефон и BlackBerry:

  • Blackberry Z10 : 720px x 1280px, 355 ppi
  • Nokia Lumia 520 : 400 пикселей на 800 пикселей, 233 пикселей на дюйм
  • Nokia Lumia 1520 : 1080px x 1920px, 367 ppi

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

5. Экспорт графики


6. Интерфейс Unity


7. Интерфейс игры


Пользовательский интерфейс нашей игры будет простым. Вы можете найти обложку этого урока в исходных файлах этого урока.

8. Язык

Если вы решите использовать другой язык, обязательно посмотрите справочник сценариев Unity для примеров.

9. 2D Графика

Unity стала отличной платформой для создания 3D-игр для различных платформ, таких как Microsoft Xbox 360, Sony PS3, Nintendo Wii, Интернет и различные мобильные платформы.

Несмотря на то, что всегда было возможно использовать Unity для разработки 2D-игр, только в выпуске Unity 4.3 была включена нативная поддержка 2D. На следующих шагах мы научимся работать с изображениями в качестве спрайтов вместо текстур.

10. Звуковые эффекты

11. Импорт активов


Прежде чем мы начнем кодировать, нам нужно добавить наши активы в проект Unity. Есть несколько способов сделать это:

  • выберите Импортировать новый актив в меню Активы
  • добавить элементы в папку активов в вашем проекте
  • перетащите активы в окно проекта

12. Создать сцену

Мы готовы создать сцену нашей игры, перетаскивая объекты на панель Иерархия или Сцена .


13. Фон


14. Корабль

Корабль также является статическим элементом, с которым игрок не сможет взаимодействовать. Поместите это в центр сцены.


15. Сарай


16. Сарай Коллайдер

Чтобы убедиться, что сарай уведомляется, когда корова попадает в него — входит в сарай, — нам нужно добавить компонент, Box Collider 2D, если быть точным.


Мы хотим, чтобы корова реагировала на попадание в дверь сарая, поэтому нам нужно сделать коллайдер немного меньше. Откройте Инспектор и измените значения размера и центра коллайдера, чтобы переместить коробку ближе к двери сарая.


17. Сценарий столкновения сарая

Пришло время написать код. Нам нужно добавить скрипт, чтобы приложение могло реагировать на столкновение, когда корова входит в сарай.


Откройте только что созданный файл и добавьте следующий фрагмент кода.

Фрагмент проверяет наличие столкновения между объектом, с которым связан скрипт, сараем и объектом с именем cow(Clone) , который будет экземпляром Prefab для коровы, который мы создадим позже. Когда происходит столкновение, воспроизводится звук и объект коровы уничтожается.

18. Амбар-Саунд


Снимите флажок Play on Awake и нажмите маленькую точку справа под значком шестеренки, чтобы выбрать звук сарая.


19. Рэй


20. Ray Script

Создайте новый скрипт, повторив шаги, которые я обрисовал несколько минут назад. Назовите скрипт Bullet и замените его содержимое следующим фрагментом кода:

if (this.transform.position.y Это много кода, но это не сложно. Посмотрим, что происходит. Сначала мы создаем экземпляр AudioClip именем cowSound , который мы будем использовать для хранения аудиофайла. Это просто еще один метод воспроизведения звука, если вы не хотите добавлять два аудио компонента к объекту. Мы объявляем переменную как общедоступную, чтобы получить доступ к ней из Инспектора . Нажмите на маленькую точку справа от cowSound и выберите аудиофайл.

Затем мы делаем луч невидимым, отключив его средство визуализации. Мы используем один и тот же объект, чтобы сэкономить ресурсы, что является важной оптимизацией для менее мощных устройств.

Мы обнаруживаем касания на экране, которые делают луч видимым и воспроизводят звук луча (см. Ниже). Если объект виден, это означает, что он должен опускаться, чтобы ударить корову.

Также есть код для определения, находится ли луч за пределами сцены. Если это так, мы перемещаем его, снова готовая к выстрелу (проверьте значения x и y луча в Инспекторе ).

Последняя часть проверяет, попадает ли луч в корову. Если это так, он воспроизводит звук коровы и уничтожает корову. Луч становится невидимым и перемещается в исходное положение, снова готовый к стрельбе.

21. Ray Audio Source


22. Добавить корову


23. Жесткое тело 2D

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


24. Коровий коллайдер

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

25. Переместить корову сценарий

Добавьте компонент сценария в корову и замените его содержимое следующим:

Unity - Полное руководство для начинающих по разработке игр ?

? Игры

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

Вступление

Эта статья предназначена для всех, кто никогда раньше не использовал Unity, но имеет некоторый опыт программирования или веб-дизайна / разработки. К концу этой статьи у вас должен быть хороший общий обзор движка, а также всех необходимых функций и кода для начала создания базовой игры.

Почему Unity?

Если вы хотите делать игры

Когда дело доходит до разработки инди-игр, вариантов действительно очень мало. Если вы хотите создавать игры, есть три основных варианта: Unreal, Unity или GameMaker.

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

В Unity есть множество очень успешных игр, таких как Escape from Tarkov (FPS), Monument Valley (Puzzler) и This War of Mine (Стратегия / Выживание).

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


Если вы хотите прототипировать пользовательский опыт

Поскольку Unity — это всего лишь движок с кучей физики, анимации и 3D-рендеринга в реальном времени, это также отличное место для создания полноценных интерактивных прототипов для исследований UX.

Unity полностью поддерживает VR и AR и, следовательно, может стать отличным инструментом для изучения архитектуры, автоматизации и моделирования с помощью клиентов.

Окно редактора Unity

Окно редактора разделено на несколько разделов. Мы расскажем об этом очень кратко, так как будем постоянно к нему обращаться на протяжении всей статьи. Если вы уже знакомы с этим, пропустите мимо!

Просмотр сцены: позволяет размещать и перемещать игровые объекты в сцене.

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

Инспектор: предоставьте подробную информацию о выбранном GameObject в сцене.

Assets / Project: здесь хранятся все префабы, текстуры, модели, скрипты и т. Д.

Иерархия: позволяет вложение и структурирование игровых объектов внутри сцены.

Теперь мы готовы начать!

Объекты Unity Game

Что такое GameObjects

Если у вас есть опыт веб-дизайна, вы можете думать о GameObjects как о элементах

! Чрезвычайно скучные контейнеры, но они легко расширяемы для создания сложной функциональности или визуальных эффектов.

Буквально все, от эффектов частиц, камер, игроков, элементов пользовательского интерфейса… (список продолжается) — это GameObject.

Создание иерархии

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

Беспорядок и эффективность

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

Позиционирование

Unity Translation: вы создали группу дронов-помощников, которые летают вокруг игрока. На самом деле вы бы не стали писать код, чтобы они гонялись за игроком, поэтому вместо этого вы создаете их как дочерние элементы игрового объекта player.

Встроенные компоненты Unity

Компонентная модель актера

Unity работает на основе модели компонентов акторов, проще говоря, GameObjects — это актеры, а компоненты — ваши скрипты.

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

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

Ключевые встроенные компоненты

Думаю, пришло время привести несколько примеров встроенных компонентов, предоставляемых движком Unity Games.

  • MeshFilter: позволяет назначать материалы для 3D-сетки GameObject.
  • MeshRender: позволяет назначать материалы 3D-сетке.
  • [Коробка | Mesh] Collider: позволяет обнаруживать GameObject во время столкновений.
  • Rigidbody: позволяет реалистичному физическому моделированию воздействовать на GameObjects с 3D-сетками и запускать события обнаружения на коллайдерах боксов.
  • Свет: освещает части вашей сцены.
  • Камера: определяет область просмотра игрока, которая будет прикреплена к GameObject.
  • Различные компоненты холста пользовательского интерфейса для отображения графического интерфейса пользователя

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

Создание пользовательских компонентов

Структура моноповедения

Ключевые функции

Все компоненты наследуются от класса MonoBehaviour. Он включает в себя несколько стандартных методов, главное:

  • void Start (), который вызывается всякий раз, когда объект, содержащий скрипт, создается в сцене. Это полезно в любое время, когда мы хотим выполнить некоторый код инициализации, например. установить экипировку игрока после того, как он появится в матче.
  • void Update (), который вызывается каждый кадр. Это то место, где будет выполняться основная часть кода, включающего пользовательский ввод, обновляющего различные свойства, такие как движение игрока в сцене.

Переменные инспектора

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

Другой пример, когда мы можем захотеть это сделать, — это создание компонента пользовательского интерфейса, который отслеживает движения мыши пользователя и помещает курсор в область просмотра. Здесь мы можем захотеть контролировать чувствительность курсора к движениям (если пользователь использовал джойстик или геймпад, а не компьютерную мышь). Таким образом, имеет смысл сделать эти переменные легко изменяемыми как в режиме редактирования, так и поэкспериментировать с ними во время выполнения.

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

Мы можем сделать это легко, просто объявив их как общедоступные переменные в теле компонента.

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

Принятие пользовательского ввода

Конечно, мы хотим, чтобы наша игра реагировала на ввод пользователя. Наиболее распространенные способы сделать это — использовать следующие методы в функции Update () компонента (или в любом другом месте, которое вам нравится):

Управление игровыми объектами

Трансформации

Все GameObjects имеют свойство transform, которое позволяет выполнять различные полезные манипуляции с текущим игровым объектом.

Вышеупомянутые методы довольно понятны , просто обратите внимание, что мы используем gameObject в нижнем регистре для ссылки на GameObject, которому принадлежит этот конкретный экземпляр компонента.

В общем, рекомендуется использовать локальное [Положение, Вращение], а не глобальное положение / поворот объекта. Обычно это упрощает перемещение объектов разумным образом, поскольку ось локального пространства будет ориентирована и центрирована на родительском объекте, а не на мировом начале координат и направлениях x, y, z.

Преимущества локального пространства станут немного более очевидными с диаграммой!

Если вам нужно преобразовать между локальным и мировым пространством (что часто бывает), вы можете использовать следующее:

Создание новых игровых объектов

Поскольку GameObjects — это в основном все в вашей сцене, вы можете иметь возможность генерировать их на лету. Например, если у вашего игрока есть какая-то пусковая установка для снарядов, вы можете захотеть создавать снаряды на лету, у которых есть собственная инкапсулированная логика для полета, нанесения урона и т. Д.

Сначала нам нужно ввести понятие префаба . Мы можем создать их, просто перетащив любой GameObject в иерархии сцены в папку с ресурсами.

По сути, это хранит шаблон объекта, который только что был в нашей сцене, со всеми теми же конфигурациями.

Пример пользовательского объекта-кирпича, который используется для динамического создания кубиков Lego в сцене, к нему прикреплен набор компонентов с различными значениями по умолчанию.

Когда у нас есть эти сборные компоненты, мы можем назначить их переменным инспектора (как мы говорили ранее) для любого компонента в сцене, чтобы мы могли создавать новые GameObject, как указано в сборке, в любое время.

Доступ к другим игровым объектам и компонентам

После этого вы можете получить доступ к любому из общедоступных методов / переменных компонента, чтобы управлять GameObject. Это простой момент, однако на самом деле получить ссылку на GameObject можно несколькими способами …

Доступ через переменную инспектора

Это самый простой способ. Просто создайте общедоступную переменную для GameObject, как мы продемонстрировали ранее с префабами, и вручную перетащите ее на компонент через инспектор. Затем перейдите к переменной, как указано выше.

Доступ через теги

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

Доступ через преобразование

Доступ через SendMessage

Raycasting

Есть два сценария, в которых это может пригодиться (вероятно, их гораздо больше):

Обнаружение столкновений

Ранее мы упоминали компоненты Collider и Rigidbody, которые можно добавить к объекту. Правило для столкновений состоит в том, что один объект в столкновении должен иметь твердое тело, а другой — коллайдер (или оба имеют оба компонента). Обратите внимание, что при использовании raycasting лучи будут взаимодействовать только с объектами, к которым прикреплены компоненты коллайдера.

После настройки в любом настраиваемом компоненте, прикрепленном к объекту, мы можем использовать методы OnCollisionEnter, OnCollisionStay и OnCollisionExit для реагирования на коллизии. Получив информацию о столкновении, мы можем получить ответственность за GameObject и использовать то, что мы узнали ранее, для взаимодействия с прикрепленными к нему компонентами.

Следует отметить, что твердые тела обеспечивают физику, такую как гравитация, для объектов, поэтому, если вы хотите отключить это, вам нужно будет включить is_kinematic .

Расширенные возможности

Мы не будем вдаваться в подробности сейчас, но, возможно, в следующей статье — просто чтобы вы знали, что они существуют.

Создание графического интерфейса

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

Расширение редактора Unity

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

Анимация

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

Материалы и PBR

Unity использует физический движок рендеринга, который обеспечивает освещение в реальном времени и реалистичные материалы. Реальность такова, что вам нужно либо сначала изучить 3D-моделирование, либо использовать модели, созданные и оптимизированные кем-то другим, прежде чем вы доберетесь до этого, чтобы создавать вещи, которые действительно хорошо выглядят.

Совет новичкам по Unity

Если вы планируете написать свою первую игру, не стоит недооценивать сложность и время, необходимое для написания даже самых тривиальных игр. Помните, что над большинством игр, которые выходят в Steam, команды работают над ними в течение многих лет!

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

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

Хорошие ресурсы для разработки игр в Unity

Сообщество разработчиков игр — одно из лучших среди всех, и в индустрии есть множество высококвалифицированных профессионалов, которые размещают контент бесплатно или почти бесплатно. В этой области требуются 3D-моделисты, концептуальные художники, геймдизайнеры, программисты и так далее. Я связал несколько отличных общих ресурсов, с которыми я столкнулся, для каждого из этих полей ниже:

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

С тех пор как разработка игр стала легко доступной для инди разработчиков, появилось не мало игр, где дизайну уделялось не такое большое внимание, а все силы уходили именно на геймплей. Позже разработчики пришли к тому, что стали доверять машинам и алгоритмам генерации. Самый яркий пример таких игр с генерируемыми мирами, это конечно же – Minecraft , где весь ландшафт состоит из блоков, хоть это и является иллюзией – ведь хранить даже обозримое кол-во блоков в оперативной памяти невероятно затратно, и все что мы видим в игре на самом деле это один большой “ супермеш ”.

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

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

Геймплей

Сначала разберем то, что будет из себя представлять будущая игра, точнее, нужно придумать примерно абстрактную модель генерируемого мира в игре. Пусть это будет простая 2D игра, где персонажу необходимо попасть из точки А в точку Б в случайно сгенерируемом уровне.

Сцена состоит из 2D блоков, которые будут случайным образом сгенерированы перед прохождением.


Процесс игры разобьем на три этапа:

  • Генерация уровня. Сперва необходимо будет сгенерировать уровень, состоящий из блоков.
  • Прохождение уровня. Помещаем персонажа на сцену и проходим уровень.
  • Завершение игры. Уничтожаем старый уровень и переходим к созданию нового.

Генерация уровня

Уровень будет состоять из блоков, разного типа:

  • Стартовый блок. Это именно то место, откуда игрок будет начинать свое путешествие.
  • Конечный блок. При попадании игрока на последний блок уровня, игра считается пройденной.


  • Промежуточный блок. Из этих блоков будет состоять большая часть уровня.


Именно кол-во промежуточных блоков будет влиять на дизайн и длину уровня.

Программная часть генерации блоков

Создадим скрипт Control , где укажем три переменных спрайтовых ( Sprite ) переменных для каждого типа блока.

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. >

В эти три переменные занесем каждый спрайт блока по отдельности: стартовый, промежуточный и конечный. Дополним скрипт Control стартовым методом Start .

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. publicvoid Start () <>
  6. >

В методе Start мы будем запускать генерацию уровня во время старта игры.

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. publicvoid Start () <>
  6. private IEnumerator OnGeneratingRoutine () <>
  7. >

В методе OnGeneratingRoutine , будем выполнять сам процесс генерации уровня. Так как уровни у нас могут быть как большими, так и маленькими и генерироваться разное количество времени, процесс генерации мы поместим в корутину, чтобы игра не “ зависала ” во время работы “ генератора ”. Далее добавим одну числовую переменную completeLevels, с помощью которой будем указывать количество пройденных уровней.

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. privateint completeLevels = 0 ;
  6. publicvoid Start () <>
  7. private IEnumerator OnGeneratingRoutine () <>
  8. publicvoid CompleteLevel ()
  9. this . completeLevels += 1 ;
  10. >
  11. >

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

Теперь можно переходить к методу OnGeneratingRoutine , где мы начнем описывать сам алгоритм генерации уровня.

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. privateint completeLevels = 0 ;
  6. /*…остальной код…*/
  7. private IEnumerator OnGeneratingRoutine ()
  8. Vector2 size = new Vector2 ( 1 , 1 );
  9. Vector2 position = new Vector2 ( 0 , 0 );
  10. yieldreturn new WaitForEndOfFrame ();
  11. >
  12. >

Для начала в методе OnGeneratingRoutine объявим две векторные переменные: size , где укажем размер блоков по длине и высоте и position, где укажем точку, откуда будет начинать строится уровень. Теперь можно построить стартовый блок.

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. privateint completeLevels = 0 ;
  6. /*…остальной код…*/
  7. private IEnumerator OnGeneratingRoutine ()
  8. Vector2 size = new Vector2 ( 1 , 1 );
  9. Vector2 position = new Vector2 ( 0 , 0 );
  10. GameObject newBlock = new GameObject ( “ Start block” );
  11. yieldreturn new WaitForEndOfFrame ();
  12. >
  13. >

Создаем новый GameObject newBlock на сцене.

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. GameObject newBlock = new GameObject ( “ Start block” );
  5. newBlock . transform . position = position ;
  6. newBlock . transform . localScale = size ;
  7. SpriteRendere renderer = newBlock . AddComponent SpriteRenderer >();
  8. renderer . sprite = this . startBlock ;
  9. yieldreturn new WaitForEndOfFrame ();
  10. >

После создания нового блока, устанавливаем ему позицию и размер через его transform , добавляем блоку компонент SpriteRenderer, чтобы отобразить на сцене и указываем, какой именно спрайт ему отобразить, в нашем случае это будет стартовый спрайт первого блока startBlock .

Теперь запустим корутину OnGeneratingRoutine в методе Start и проверим ее выполнение.

Переходим к созданию промежуточных блоков. Для этого в корутине OnGeneratingRoutine добавим еще одну переменную count .

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. GameObject newBlock = new GameObject ( “ Start block” );
  5. newBlock . transform . position = position ;
  6. newBlock . transform . localScale = size ;
  7. SpriteRendere renderer = newBlock . AddComponent SpriteRenderer >();
  8. renderer . sprite = this . startBlock ;
  9. int count = this . completeLevels + 5 ;
  10. yieldreturn new WaitForEndOfFrame ();
  11. >

Числовая переменная count будет указывать какое кол-во промежуточных блоков необходимо построить, это число будет зависеть от количества пройденных уровней и, чтобы их изначально не было слишком мало на первых уровнях, еще пяти (5) дополнительных блоков. Строить промежуточные блоки будем через цикл for .

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. GameObject newBlock = new GameObject ( “ Start block” );
  5. newBlock . transform . position = position ;
  6. newBlock . transform . localScale = size ;
  7. SpriteRendere renderer = newBlock . AddComponent SpriteRenderer >();
  8. renderer . sprite = this . startBlock ;
  9. int count = this . completeLevels + 5 ;
  10. for ( int i = 0 ; i count ; i ++)
  11. newBlock = new GameObject ( “ Middle block” );
  12. renderer = newBlock . AddComponent SpriteRenderer >();
  13. renderer . sprite = this . midBlock ;
  14. >
  15. yieldreturn new WaitForEndOfFrame ();
  16. >

Также как мы строили стартовый блок, также строим и промежуточные: создаем новый GameObject , добавляем ему компонент SpriteRenderer , указываем спрайт для отображения на сцене и задаем размер и позицию.

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

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. /*…остальной код…*/
  5. int count = this . completeLevels + 5 ;
  6. for ( int i = 0 ; i count ; i ++)
  7. newBlock = new GameObject ( “ Middle block” );
  8. renderer = newBlock . AddComponent SpriteRenderer >();
  9. renderer . sprite = this . midBlock ;
  10. newBlock . transform . localScale = size ;
  11. position . x += size . x ;
  12. newBlock . transform . position = position ;
  13. >
  14. yieldreturn new WaitForEndOfFrame ();
  15. >

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

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. /*…остальной код…*/
  5. int count = this . completeLevels + 5 ;
  6. for ( int i = 0 ; i count ; i ++)
  7. newBlock = new GameObject ( “ Middle block” );
  8. renderer = newBlock . AddComponent SpriteRenderer >();
  9. renderer . sprite = this . midBlock ;
  10. newBlock . transform . localScale = size ;
  11. position . x += size . x ;
  12. position . y += size . y * Random . Range (- 1 , 2 );
  13. newBlock . transform . position = position ;
  14. >
  15. yieldreturn new WaitForEndOfFrame ();
  16. >

Высота блока по Y в переменной position также смещается вверх, либо вниз, в зависимости от размера блока, умноженного на случайное число от -1 до 1. Метод Random.Range генерирует ЦЕЛЫЕ числа от минимального до максимально (ИСКЛЮЧИТЕЛЬНО), это значит, что максимальное указанное число никогда достигнуто не будет. Завершаем цикл постройки промежуточных блоков новым WaitForEndOfFrame .

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. /*…остальной код…*/
  5. int count = this . completeLevels + 5 ;
  6. for ( int i = 0 ; i count ; i ++)
  7. newBlock = new GameObject ( “ Middle block” );
  8. renderer = newBlock . AddComponent SpriteRenderer >();
  9. renderer . sprite = this . midBlock ;
  10. newBlock . transform . localScale = size ;
  11. position . x += size . x ;
  12. position . y += size . y * Random . Range (- 1 , 2 );
  13. newBlock . transform . position = position ;
  14. yieldreturn new WaitForEndOfFrame ();
  15. >
  16. yieldreturn new WaitForEndOfFrame ();
  17. >

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

  1. private IEnumerator OnGeneratingRoutine ()
  2. Vector2 size = new Vector2 ( 1 , 1 );
  3. Vector2 position = new Vector2 ( 0 , 0 );
  4. /*…остальной код…*/
  5. newBlock = new GameObject ( “ End block” );
  6. renderer = newBlock . AddComponent SpriteRenderer >();
  7. renderer . sprite = this . endBlock ;
  8. position . x += size . x ;
  9. position . y += size . y * Random . Range (- 1 , 2 );
  10. newBlock . transform . position = position ;
  11. newBlock . transform . localScale = size ;
  12. yieldreturn new WaitForEndOfFrame ();
  13. >

Готово, алгоритм генерации завершен, запускаем игру для последней проверки.

Заключение

Чтобы генерация уровня происходила каждый раз когда игрок завершает игру, в методе CompleteLevel достаточно просто запустить корутину OnGeneratingRoutine заново.

  1. publicclass Control : MonoBehaviour
  2. public Sprite startBlock ;
  3. public Sprite midBlock ;
  4. public Sprite endBloc ;
  5. privateint completeLevels = 0 ;
  6. publicvoid Start () <>
  7. private IEnumerator OnGeneratingRoutine () <>
  8. publicvoid CompleteLevel ()
  9. this . completeLevels += 1 ;
  10. StartCoroutine ( OnGeneratingRoutine ());
  11. >
  12. >

Сам алгоритм генерации достаточно простой, его можно расширить и дополнить новыми элементами блоков: ловушками, пропастями и тд. Добавить блокам коллайдеры и персонажа, который сможет перемещать по ним.

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

Инстанцирование префабов.

В предыдущей статье было описано создание Префабов. Вы можете дополнительно почитать про префабы ТУТ. После того как Вы создали префаб вы можете быстро и легко сделать его копию, называемую Экземпляром (Instance). Для создания экземпляра префаба перетащите его из окна Проекта в Иерархию или Сцену. Теперь Вы имеете экземпляр Вашего префаба и можетет его позиционировать и настроить по желанию.

Добавление компонентов и скриптов.

После выбора префаба или любого игрового объекта Вы можете добавить функциональность к нему и спользуя Компоненты. Пожалуйста изучите Справку по компонентам. Скрипты - это тоже один из типов компонентов. Для добавления компонента просто выберите нужный объект и выберите компонент из Меню компонентов. После этого Вы увидите компонент в Инспекторе. Скрипты также содержатся в Меню компонентов.

Если добвление компонента разрывает связь объекта с префабом, Вы всегда можете использовать GameObject->Apply Changes to Prefab из меню для восстановления связи.

Размещение объектов.

После размещения объекта в сцене Вы можете использовать Инструмент Transform для позиционирования его. Добавочно Вы можете напрямую задавать значения в Инспекторе для точного размещенеия и поворота. Прочитайте страницу Компонент Transform для дополнительной информации о позиционировании и повороте объектов.

Работа с камерами.

Камеры - глаза Вашей игры. Все что видит игрок проигрывается одной или несколькими камерами. Камера это обычный объект игры с прикрепленным к нему компонентом камеры. Вы можете позиционировать, повернуть или удочерить камеру точно так же как любой ино объект игры. Т.е. она может делать все, что делают обычные объекты, плюс некоторые специфичные для камер функции. Есть некоторые полезные скрипты камер поставляемые с Юнити. Они могут быть включены в Ваш проект сразу, или Вы можете использовать меню Assets->Import Package. Скрипты, которые Вы импортируете могут быть найдены в меню Components->Camera-Control. Есть некоторые дополнительные тонкости использования камер, которые хорошо бы изучить. Для этого почитайте страницу по компоненту Camera.

Светильники.

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

Читайте также: