МИНИCTEPCTBO НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ АВТОНОМНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ОБРАЗОВАНИЯ «СЕВЕРО-КАВКАЗСКИЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ» Методические указания по выполнению лабораторных работ по дисциплине «РАЗРАБОТКА ИГРОВЫХ ПРИЛОЖЕНИЙ» для студентов направления подготовки /специальности 09.03.03 Прикладная информатика шифр и наименование направления подготовки/ специальности (ЭЛЕКТРОННЫЙ ДОКУМЕНТ) Оглавление Лабораторная работа №1. Знакомство с Unity 3D ..................................... 4 Лабораторная работа №2. Работа с ландшафтом в Unity ........................ 27 Лабораторная работа №3. Работа с ландшафтом в Unity (наполнение ландшафта, высадка растительности) ................................................................. 48 Лабораторная работа №4. Создание простой игры в 2D Unity .............. 58 Лабораторная работа №5. Создание простой 2D игры на Unity (физика и механика) ............................................................................................................ 76 Лабораторная работа №6. Создание простой 2D игры в Unity (скриптинг и публикация) .................................................................................... 90 Лабораторная работа №7. Создание дорог в Unity ................................ 118 Лабораторная работа №8. Добавление автомобиля в Unity ................. 123 Лабораторная работа №9. Работа со звуком в Unity ............................. 130 Лабораторная работа №1. Знакомство с Unity 3D 1. Цель и содержание Цель лаботаторной работы: получить практические знания и навыки по работе со средой разработки игр Unity. 2. Теоретическая часть Unity – это инструмент для разработки двух- и трёхмерных приложений и игр, работающий под операционными системами Windows, Linux и OS X. Созданные с помощью Unity приложения работают под операционными системами Windows, OS X, Windows Phone, Android, Apple iOS, Linux, а также на игровых приставках Wii, PlayStation 3, PlayStation 4, Xbox 360, Xbox One и MotionParallax3D дисплеях (устройства для воспроизведения виртуальных голограмм), например, Nettlebox. Есть возможность создавать приложения для запуска в браузерах с помощью специального подключаемого модуля Unity (Unity Web Player), а также с помощью реализации технологии WebGL. Ранее была экспериментальная поддержка реализации проектов в рамках модуля Adobe Flash Player, но позже команда разработчиков Unity приняла сложное решение по отказу от этого. Приложения, созданные с помощью Unity, поддерживают DirectX и OpenGL. Активно движок используется как крупными разработчиками (Blizzard, EA, QuartSoft, Ubisoft), так и разработчиками Indie-игр (например, ремейк Мор. Утопия (Pathologic), Kerbal Space Program, Slender: The Eight Pages, Slender: The Arrival, Surgeon Simulator 2013, Baeklyse Apps: Guess the actor и т. п.) в силу наличия бесплатной версии, удобного интерфейса и простоты работы с движком. Интерфейс Unity представлен на рисунке ниже. Рассмотрим основные вкладки Unity: Вкладка Project представляет собой файловый менеджер для папки Assets. Папка Assets это основная папка проекта, в которой хранятся практически все файлы игры (аудио, изображения, скрипты). Вкладка Console служит ля вывода ошибок, или для вывода пользовательских сообщений из кода Вкладка Hierarchy отображает все объекты находящиеся в данный момент на данной сцене, кнопочка create позволяет создавать объекты Вкладка Inspector отображает характеристики выбранного объекта Вкладка Scene отображает сцену, то есть все объекты как они будут отображаться в игре. По сути это наша рабочая область. В ней можно передвигать объекты изменять их размер и т.д. Вращать камеру можно с помощью правой клавиши мыши. Вкладка Game отображает непосредственно игру. Она не позволяет проводить манипуляции с объектами и становиться активной при запуске. кнопка позволяет перемещаться по сцене кнопка позволяет изменять размеры объектов кнопка позволяет вращать объекты кнопка позволяет изменять размеры объектов кнопка позволяет проводить над объектами сразу все манипуляции (растягивать, перемещать и вращать) кнопка запуска игры кнопка паузы игры кнопка служит для просмотра игры по кадрам Кратко рассмотрим виды объектов: – Клавиша Create Empty служит для созданий «Пустого объекта», обычно служит для группировки объектов – Клавиша Create Empty Child служит для созданий «Пустого дочернего объекта», про дочерние объекты будет описано ниже. – 3D Object – Cube – куб – Sphere – сфера – Capsule – капсула – Cylinder – цилиндр – Plane – плоскость – И другие. – 2D Object – спрайты (то есть 2д текстуры) – Light – объекты, издающие свет – Audio – аудио компонент (например, музыка на заднем фоне) – UI – компоненты пользовательского интерфейса, например, кнопки текст и другие. – Camera – это камеры игры, точки с которых можно смотреть на игру, их можно установить несколько. Дочерние объекты, наследуют свойство родительских объектов, например, при повороте родительского объекта дочерний так же будет поворачиваться, но дочерние объекты можно изменять без изменения родительских объектов. Так же к объектам можно добавлять компоненты в панели Inspector. компоненты – это различные эффекты, физика, аудио и т.д., например, компонент Box Collider позволяет указать что объект является твердым (он подходит для кубических объектов). Последнее важное понятие – это понятие «Префаба». Префабы создаются из объектов. Для его создания нужно перетащить объект в папку Assets. После этого там появиться наш объект, который мы можем копировать на сцену. Префабы нужны для того что бы изменять свойства всех экземпляров нашего объекта. Например, мы перенесли 300 кубов на сцену, а потом решили изменить их цвет. Нам нужно изменить цвет каждого куба по-отдельности что не очень удобно. Для этого и служат префабы. Мы можем изменить цвет только префаба в папке assets и цвет измениться у всех его «экземпляров». Префаб это повторяющиеся вещи в игре, они являются клонами и занимают меньше памяти в игре. Порядок выполнения работы Для создания тестовой игры будем официальном использовать пример на сайте Unity игру Roll-a- ball (https://unity3d.com/ru/learn/tutorials/projects/roll-ball-tutorial). Запустим Unity и создадим новый проект нажатием на кнопку , выберем путь где будут храниться исходники нашей игры. Введите имя игры. Выберем режим 3D и создадим проект. После запуска проекта создам файловую структуру проекта. В папке Assets создадим 4-ре папки: – _Scenes – в этой папке будут храниться наши сцены – Materials – в этой папке будут храниться наши материалы – Prefabs – в этой папке будут храниться наши «префабы» – Scripts – в этой папке будут храниться наши скрипты Сохраним нашу сцену, в папке сцен сочетанием клавиш ctrl+s либо через меню File – Save Scene. Вводим любой название мы введем «game» Теперь создам поле для нашей игры. Нажмем кнопку Create в вкладке Hierarchy выберем 3D Object – Plane (плоскость). После этого должна появиться плоскость в окне Scene. Используя вкладку Inspector переименуем область. Назовем ее «Ground» и нажмем клавишу enter. Сбросим значение Transform используя кнопку Reset. Для отображения, выпадающего меню нажмем на значок шестерёнки. Рассмотрим вкладку Transform в инспекторе – Position – отвечает за положение объекта в пространстве – Rotation – отвечает за поворот объекта в пространстве – Scale – отвечает за размер объекта Теперь добавим игрока на наше поле, в данном случае игроком будет выступать сфера. Аналогичным образом сбросим значения transform для сферы. Переименуем сферу в «Player» и установим свойство Position значение 0.5 для того чтобы наша сфера соприкасалась с плоскостью как на рисунке. Так же можно по изменять свойства transform для объекта Directional Light, который отвечает за свет. Этим займитесь самостоятельно. Мой результат представлен на рисунках. Теперь изменим цвет земли и сферы. Для этого в папке materials добавим новые материалы. В папке нажмем правой кнопкой мышки Create – Material В папке появится новый материал. Введите для него любое имя. Теперь выберем для него цвет. Для этого выберем элемент и в вкладке инспектора установим свойству Shader значение Unlit - Color После этого в Main Color выберем нужный цвет. Теперь перетащим созданный материал на нужный нам объект во вкладке Hierarchy либо выберем целевой объект и перетащим материал в инспектор. При этом в инспекторе целевого объекта появиться добавленный материал В результате должно получиться нечто подобное. Проверим что бы у сферы и у земли были установлены свойства Collider (галочка рядом с именем должна быть включена). Эти свойства указывают что эти объекты твердые. Теперь сфере добавим новый компонент physics – Rigidbody. Этот компонент показывает, что элемент подчиняется законам физики. Это нужно для того чтобы объект мог двигаться по земле. Следующим шагом мы создадим логику управления сферой. Для этого добавим в папку Scipts скрипт C#. Назовем скрип PlayerController. Привяжем скрипт к нашему объекту, аналогично как мы привязывали материалы. Теперь откроем созданый скрипт. Его можно открыть как MonoDevelop так и в Visual Studio Видим структуру кода, класс PlayerController наследуется от класса MoniBehaviour который является основным классом в Unity. Функция Start вызывается один раз в начале вместе с первым кадром сцены. Функция Update вызывается каждый кадр в сцены. В Unity существует множество функций, но это самые популярные из них. Изменим код класса на следующий: public float speed; private Rigidbody rb; void Start () { rb = GetComponent<Rigidbody>(); } private void FixedUpdate() { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); rb.AddForce(movement * speed); } Переменная «speed» отвечает за скорость перемещения. Переменная «rb» отвечает за хранение компонента «Rigidbody» данного объекта, рассмотренного ранее. Получение компонента происходит в методе Start. Функция FixedUpdate аналогична функции Update, но вызывается не каждый кадра, а через определенное время. Input.GetAxis("Horizontal") Получает от пользователя нажатии стрелки вправо или влево. Принимает значение от 1 до -1. Вправо 1, влево -1. Увеличение происходит постепенно. Input.GetAxis("Vertical") Получает от пользователя нажатии стрелки вниз или вверх аналогично Input.GetAxis("Horizontal") Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); В этой строке мы создаем вектор направления движения. Vector3 содержит три координаты так как мы работаем в трехмерном пространстве, существует так же Vector2. rb.AddForce(movement * speed); В этой строке нашему элементу добавляется сила вдоль направления вектора которая приводит к движению. Теперь в Unity в инспекторе нашей сферы должно появиться поле для задания скорости (любые публичные переменные или поля будут отображаться в этой области). Введите значение 6. После этого мы можем запустить нашу игру и проверить, если все сделано сфера должна перемещаться с помощью стрелок. Теперь будем осуществлять работу с камерой, установим камеру чтобы область в окне Game выглядела примерно так Теперь привяжем нашу камеру к сфере. Для этого создайте новый скрипт и назовите его Camera и прикрепите его к нашей камере. Добавим следующий код. public GameObject player; private Vector3 offset; // Use this for initialization void Start () { offset = transform.position - player.transform.position; } // Update is called once per frame void LateUpdate () { transform.position = player.transform.position + offset; } GameObject player; хранит объект сферы offset = transform.position - player.transform.position; получаем отступ от камеры до объекта отнимая позицию объекта от позиции камеры transform.position = player.transform.position + offset; меняем позицию камеры устанавливая позицию объекта плюс отступ. Функция LateUpdate вызывается в конце кадра после функций Update. Не забудьте в инспекторе передать объект сферы классу камеры всех Теперь самостоятельно создайте стены нашей области, как представлено на рисунке, используя элементы Cube для того чтобы сфера не выпадала за пределы области. Создадим новый куб, зададим ему размеры как представлено на рисунке Добавим новый скрипт назовем его Rotate. Скрипт нужен для анимации кубиков. Перенесем скрипт на только что добавленный куб и откроем его. Добавим код для вращения кубика. void Update() { transform.Rotate(new Vector3(15, 35, 28) * Time.deltaTime); } Функция Rotate производит вращение объекта по заданному вектору. Вектор умножается на время для того чтобы вращение происходило плавно. Делая вращение зависимым от времени, а не от кадров. Сделаем из нашего кубика префаб перетащив его в папку Prefabs. Создадим пустой объект и назовите его Cubes.Теперь используя созданный префаб добавьте в наш пустой еще несколько кубиков. А также уже созданный куб перенесите в пустой объект. Теперь создайте новый материал как мы это делали ранее. Выберите любой цвет. Сделайте активным наш префаб в вкладке project и добавьте ему материал, перетащив его в инспектор исходного куба для префаба. Если вы все сделали правильно все кубики изменят цвет. Нашему префабу в инспекторе установим галочку Is Trigger. Эта галочка позволяет другим элементам проходить сквозь этот элемент, но при этом отслеживать соприкосновения с ним (если просто снять галочку Box Collider, то мы так же сможем проходить сквозь элемент, но не сможет отследить соприкосновение) Выберите наш префаб и в инспекторе нажмите Tag – add Tag В открывшемся окне нажмите плюс и введите имя тега «cubes» (без кавычек) и нажмите save снова выберете наш префаб и установите ему только что добавленный тег. Откроем скрипт PlayerController и добавим следующий код private void OnTriggerEnter(Collider other) { if (other.tag == "cubes") Destroy(other.gameObject); } Функция OnTriggerEnter отслеживает прикосновение с объектом, в качестве параметра принимает объект, с котором произошло соприкосновение. Потом мы проверяем если это объект с тегом cubes то удаляем его. Теперь мы можем собирать кубики. Проверьте это, запустив игру. Реализуем механизм подсчета собранных кубиков и вывод надписи после сбора все кубиков. Создадим текстовое поле Create - UI – Text. Выбираем Text и изменим его имя на CountText, а затем нажимаем на квадрат в инспекторе. После этого у нас появиться окно выбора положения, зажимаем alt+shift и выбираем квадрат, указанный на рисунке. Текст должен закрепиться в левом верхнем углу экрана. После этого введите значения в поля как на рисунке. Так же ниже вы можете изменить размер шрифта, цвет и стиль. Аналогичным образом добавьте еще один текст только сделайте выравнивание по центру экрана. Назовите его «WinText». Затем откройте скрип PlayerController. В блок using добавьте using UnityEngine.UI; Так же в класс добавьте следующие поля public Text countText, winText; Вернемся в Unity и добавим ссылку на тексты в это текстовое поле, в инспекторе объекта сферы Возвращаемся к скрипту PlayerController изменим код класса на следующий public float speed; private Rigidbody rb; /// количество собранных кубов private int count; /// Изначальное количество кубов private int countCoub; /// текстовые поля public Text countText, winText; void Start () { rb = GetComponent<Rigidbody>(); count = 0; /// по умолчанию собрано 0 кубов winText.text = ""; /// текст победы по умолчанию скрыт /// получаем количество элементов с тегом cubes countCoub = GameObject.FindGameObjectsWithTag("cubes").Length; setCount(); } private void FixedUpdate() { float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); rb.AddForce(movement * speed); } private void OnTriggerEnter(Collider other) { if (other.tag == "cubes") { Destroy(other.gameObject); count++; setCount(); } } /// <summary> /// Функция изменения текстов /// </summary> private void setCount() { countText.text = "Количество: " + count.ToString(); if(count >= countCoub) winText.text = "Победа!!!"; } Самостоятельно попробуйте добавить текст, в котором будет написано сколько кубов еще нужно собрать как на рисунке. Теперь сохраним сцену (ctrl+s) и зайдем в File – Build Setting откроется окно Нажмите на кнопку add open scenes чтобы добавить открытые сцены в игру. Выберите платформу Windows нажмите клавишу build и выберите путь где будет сохранена наша игра. После этого вы можете запустить данную игру через exe файл. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно для не пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Вопросы для защиты работы 1. Что такое Unity? 2. Какие возможности предоставляет Unity? 3. Как добавить объект на сцену в Unity? 7. Задание 1. Выполните пример из лабораторной работы. 8. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №2. Работа с ландшафтом в Unity 1. Цель и содержание Цель лаботаторной работы: получить практические знания и навыки по работе с ландшафтом в Unity. 2. Теоретическая часть Инструменты ландшафтного движка Unity Unity – это мультиплатформенный игровой движок, разработанный Unity Technologies, который используется для создания видеоигр и приложений для множества устройств (ПК, консолей, мобильных устройств и даже веб-сайтов). Основными преимуществами Unity являются его надежность и мобильность; Unity нацеливается на несколько известных API, таких, как Direct3D, OpenGL, OpenGL ES и недавний Vulkan. Благодаря вышеупомянутым характеристикам Unity становится все более популярным среди компаний разработчиков программного обеспечения уровня AAA и начинающих программистов. Unity поддерживает несколько технологий и компонентов. Одним из ключевых компонентов системы является ландшафтный движок. Система ландшафтов Unity позволяет создавать обширные ландшафты для ваших игр или приложений. Вы можете использовать набор инструментов для создания ландшафтов легко и быстро. Инструменты ландшафта Первый шаг – это создать новый проект Unity. Теперь добавьте новую сцену (File > New Scene). Новая сцена была создана с двумя игровыми объектами, Main Camera и Directional Light (Unity 5 автоматически добавит skybox в сцену). Теперь, чтобы добавить игровой объект terrain, перейдите в меню GameObject и выберите 3D Object > Terrain. Это добавит плоскую поверхность (называемую Terrain) в вашу сцену. Эта поверхность является сеткой, которую мы собираемся сделать для создания на этом уровне ландшафта. Если вы проверите свой каталог Assets (в нижней части интерфейса Unity), вы увидите, что был создан файл New Terrain. Выберите Terrain и посмотрите вкладку Inspector. Вы увидите, что terrain имеет три компонента: Transform, Terrain script и компонент Terrain Collider. Компонент terrain предоставляет вам инструменты, необходимые для редактирования вашего ландшафта. Все инструменты на панели инструментов, за исключением инструмента размещения деревьев и панели настроек, предоставляют набор "кистей" и параметры для настройки размера и прозрачности кисти, так же как инструменты рисования из обычного редактора изображений. Это позволяет создавать ландшафт подобно инструменту рисования. Если вы выберете любую кисть под компонентом Terrain и наведите указатель мыши на поверхность, вы увидите синюю область, проецируемую на этой поверхности. Это позволяет узнать область ландшафта, на которую повлияет ваша кисть. Как вы, возможно, уже поняли, объект Terrain довольно большой. Для навигации по Scene (сцене)вы можете использовать мышь и клавиатуру. Внутри вкладки Scene нажмите и удерживайте правую кнопку мыши (курсор должен измениться на глаз). Удерживая кнопку мыши: – Вы можете изменить угол обзора, перемещая мышь. – Используйте клавиши W, S, A, D для перемещения по 3D-сцене. Прежде чем приступать к изучению инструментов ландшафта, давайте посмотрим на свойства Terrain. Последняя кнопка на компоненте Terrain (внутри вкладки Inspector) покажет вам базовые параметры объекта terrain. Свойства делятся на разделы: Base Terrain Tree & Detail Objects Wind Settings for Grass Resolution Heightmap Внутри первой секции Base Terrain вы найдете несколько свойств и параметров. Опция Draw включает или выключает рендеринг ландшафта. Pixel Error представляет значение точности преобразования между картами terrain’а (например, текстур, heightmaps и самого сгенерированного terrain’а). Более высокие значения представляют меньшую точность, а меньшие значения будут сбалансировать окружение. приводить это значение, к излишней чтобы обработке. создать хорошее, Вы обязаны насыщенное Base Map dist. – максимальное расстояние, на котором текстуры ландшафта будут отображаться с полным разрешением. Вы можете включить или отключить тени, выбрав Cast Shadows. Затем у нас есть Material. Здесь вы устанавливаете материал, который будет использоваться для рендеринга ландшафта. Это повлияет на то, как интерпретируются цветовые каналы текстуры ландшафта. Вы можете выбрать: Built In Standard представляет материал, основанный на физическом рендеринге, который был введен в Unity 5. Если выбран этот параметр, для каждого слоя наложения можно использовать одну текстуру для альбедо и сглаживания, одну текстуру для нормали и одно скалярное значение для сдвига металла. Имейте в виду, что, если проверяется "Overwrite Smoothness", вместо того, чтобы читать из текстурных карт, ровность всего terrain'а будет контролироваться только значением Smoothness. Built In Legacy Diffuse представляет собой устаревший встроенный материал ландшафта из предыдущих релизов Unity (Unity 4 и более ранних). Он использует модель освещения Ламберта и имеет дополнительную поддержку обычной карты. Built In Legacy Specular использует модель освещения BlinnPhong и имеет дополнительную поддержку обычной карты. Этот параметр также позволяет задать общий цвет отражения и блеск для ландшафта. Опция Custom использует настраиваемый материал для вашего ландшафта. Этот материал должен быть шейдером, который ориентирован для рендеринга ландшафта. Это вариант, который я рекомендую только продвинутым пользователям. Однако, если вы хотите попробовать, взгляните на исходный код некоторых встроенных шейдеров и внесите изменения одного из них. Вы можете также установить Reflection Probes (оптические датчики) для некоторых материалов, но они будут использоваться только при использовании встроенного стандартного материала или пользовательского материала, который поддерживает рендеринг с отражением. Возможные варианты reflection probes: Off: Reflection probes отключены, и для отражения будет использоваться только skybox. Blend Probes: Reflection probes включены. Смешивание происходит только между датчиками. Если поблизости нет датчиков отражения, то будет использоваться отражение по умолчанию, но между отражением по умолчанию и датчиком не будет никакого смешивания. Blend Probes And Skybox: Reflection probes включены. Смешивание происходит между датчиками или датчиками и отражением по умолчанию. Simple: Reflection probes включены, но между датчиками не происходит смешивания, если имеется два перекрывающихся объема. Наконец, последний параметр в этом разделе – Thickness. Это значение указывает, насколько объем столкновения terrain'а должен простираться вдоль отрицательной оси Y. Считается, что объекты пересекаются с ландшафтом от поверхности до глубины, равной толщине. Это помогает предотвратить проникновение высокоскоростных движущихся объектов в ландшафт без дорогостоящего непрерывного обнаружения столкновения. Следующий раздел настроек – Tree & Detail Objects. Первая опция – Draw. Здесь можно настроить прорисовку деталей. В основном, это говорит движку, хотите ли вы, чтобы деревья и трава рисовались или нет. Затем у вас есть Bake Light Probes для деревьев. Если вы включите эту опцию, Unity создаст световые датчики в позиции каждого дерева. Затем датчики будут применены к рендерингу деревьев. Если отключить этот параметр, на деревья по-прежнему будут влиять датчики группы источников света. Обратите внимание, что этот параметр доступен только для деревьев, на которых установлены световые датчики на их префабах. Detail Distance – это расстояние от камеры, после которого детали будут отсекаться. Detail Density представляет количество объектов деталей/травы в данной условной единице площади. Tree Distance представляет собой расстояние от камеры, за которым деревья будут отсекаться. Billboard Start – это расстояние от камеры, начиная с которого 3D деревья начнут заменяться на спрайтовые изображения. Fade Length представляет собой расстояние перехода деревьев из 3D объектов в плоские спрайты. Наконец, Max Mesh Trees – максимальное количество видимых деревьев, которые будут представлены в качестве полноценных 3D мешей. Идем дальше, вы увидите параметры Wind Settings for Grass Speed определяет скорость обдувающего траву ветра. Size представляет собой размер ряби на травянистых участках. Bending позволяет определить степень, наклона объектов травы под действием ветра. Grass Tint позволяет выбрать общий оттенок цвета, применяемый к объектам травы. В разделе Resolution вы найдете несколько свойств разрешения, а именно: Terrain Width, Length, и Height. Все три имеют очень четкое значение. Heightmap Resolution – разрешение карты высот terrain’а в пикселях. Должно быть степенью двойки плюс один, например, 513 = 512 + 1. Detail Resolution позволяет определить разрешение карты. Чем выше разрешение, тем меньше и более детальны будут участки травы. Detail Resolution per Patch устанавливает длину и ширину квадрата островков, отрендеренного за один вызов рисования. Control Texture Resolution – разрешение карты splat, которая контролирует смешивание разных текстур terrain’а. Наконец, Base Texture Resolution разрешение композитной текстуры, используемой на terrain’е когда вы смотрите на него с расстояния, большего чем значение base map distance. Последний раздел – Heightmap. Здесь вы можете импортировать исходный файл heightmap в raw формате или экспортировать текущий terrain в файл изображения в RAW формате. Это может быть очень полезно, если вы хотите использовать внешнее стороннее программное обеспечение для взаимодействия с вашим приложением или игрой. Инструменты для изменения высоты Прежде чем перейти к инструментам высоты, помните, что необходимо сначала задать параметры разрешения. В противном случае, если вы попытаетесь изменить их позже, то все эти поверхности будут утеряны. Первыми тремя инструментами на панели инструментов Terrain Inspector являются инструменты изменения высоты. Эти инструменты используются для рисования изменений высоты на поверхности. Они предоставляют набор "кистей" с настройками Brush Size и Opacity; Эти инструменты очень похожи на инструменты рисования из любого редактора изображений. Они позволяют рисовать детали ландшафта, как если бы вы рисовали изображение. Если вы переместите курсор на вкладку Scene, вы увидите синюю область, проецируемую на поверхности. Это позволяет узнать область ландшафта, на которую повлияет ваша кисть. Первым инструментом является Raise / Lower Height. При рисовании с помощью этого инструмента высота ландшафта будет увеличиваться пока вы водите мышкой с зажатой левой кнопкой по terrain’у. Если удерживать мышь в одной конкретной области, высота будет суммироваться. Такой эффект визуально изображен на следующем рисунке. Чтобы опустить ландшафт, просто удерживайте клавишу Shift во время рисования инструментом, и это уменьшит высоту вашего ландшафта. Второй инструмент в редакторе ландшафта – Paint Height. Этот инструмент используется для установки целевой высоты для области ландшафта. Он работает аналогично инструменту Raise/Lower, но имеет дополнительное свойство для установки целевой высоты Height. Вы можете выбрать желаемую высоту Height, изменив значение параметра Height. Кнопка Flatten рядом с свойством height, которая просто устанавливает высоту у всего terrain’а в заданное значение Height. Наконец, третий инструмент – Smooth Height. Этот инструмент не будет резко увеличивать или уменьшать высоту terrain’а; Вместо этого он смягчит ландшафт и уменьшит появление резких изменений. Вы могли бы использовать этот инструмент, например, когда вы нарисовали деталь используя одну из "шумящих" кистей из доступного набора, поскольку эти кисти созданы для привнесения острых, скалистых камней в ландшафт и вы можете использовать этот инструмент, чтобы смягчить их. Пришло время потратить некоторое время и создать свой собственный ландшафт местности. Попытайтесь использовать вышеупомянутые три инструмента, чтобы создать красивый горный ландшафт. Инструмент для создания текстур Ландшафт создан теперь пора текстурировать его. Прежде чем двигаться дальше, вам нужно импортировать aссеты окружающей среды, доступные в Unity 5. Для этого выберите Assets > Import Package и выберите Environment. Нажмите Import, чтобы импортировать все относящийся к окружающей среде ассеты. Если версия Unity окружающей среды. старше 5.6, то вы не сможете подобным В этом случае, вам необходимо загрузить ассеты из Asset Store: образом импортировать ассеты В фильтрах необходимо ввести в строку поиска “environment”, выбрать только бесплатные, как показано на рисунке ниже: Вы можете импортировать любые понравившиеся вам ассеты, например: https://assetstore.unity.com/packages/essentials/tutorial-projects/book-of-the-deadenvironment-121175 https://assetstore.unity.com/packages/3d/environments/nature-starter-kit-2-52977 https://assetstore.unity.com/packages/3d/environments/hand-painted-forest-environment-freesample-35361 https://assetstore.unity.com/packages/3d/environments/landscapes/realistic-terrain-collectionlite-47726 https://assetstore.unity.com/packages/3d/environments/landscapes/photoscanned-moutainsrockspbr-130876 Unity позволяет рисовать ландшафты используя текстуры. Вы можете нарисовать свой ландшафт различными текстурами в разных областях. Например, вы можете иметь текстуру для скалы, другую для песка еще одну для травы. Текстуры могут применяться с различной прозрачностью, что означает, что вы можете делать плавные переходы между двумя текстурами. Для достижения наилучших результатов следует нарисовать ландшафт с бесшовными текстурами. Как вы могли заметить на вкладке Inspector, инструмент Paint Texture имеет несколько кистей и позволяет вам изменять Brush Size, Opacity и Target Strength. В первый раз, когда вы используете инструмент для рисования Texture Tool, на нем не будет текстур. Первое, что вам нужно сделать, это добавить новую текстуру в палитру. Для этого нажмите кнопку Edit Textures и выберите Add Texture. Появится новое окно. Как можно видеть, в этом окне можно выбрать Select нужную текстуру и ее обычную карту, если такова имеется. Нажмите на квадрат под текстурой и выберите текстуру. Появится окно, позволяющее выбрать текстуру. Выберите текстуру SandAlbedo и нажмите Add. Теперь ваш ландшафт должен иметь вид песка. Обратите внимание, что вы всегда можете изменить ландшафт в опциях редактирования текстуры или удалить его. Первая созданная вами текстура всегда должна быть базовой текстурой для ландшафта. Все они являются частью импортированных ассетов и могут быть найдены так же, как и текстура SandAbedo. Продолжайте и импортируйте их все. Когда у вас есть все импортированные текстуры, пришло время текстурировать ваш ландшафт, как вы хотите. Выберите текстуру и нарисуйте нужную среду. Пример текстурированной карты. Когда вы удовлетворены результатом, перейдите к следующему разделу. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно не для пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Задание 1. Создайте ландшафт и смоделируйте любой вид местности (можно использовать карту высот). 2. Текстурируйте ландшафт. 7. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, индивидуального задания. полученные в результате выполнения Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №3. Работа с ландшафтом в Unity (наполнение ландшафта, высадка растительности) 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по работе с ландшафтом в Unity. Научиться создавать префабы растительности и заполнять ландшафт деревьями и кустарниками. 2. Теоретическая часть Инструмент для создания деревьев Теперь, когда вы нарисовали свой ландшафт, пришло время добавить к нему несколько деревьев. Unity 3D позволяет размещать деревья на вашем ландшафте так же, как вы рисовали текстуры. Используя настройки спрайтов для удаленных деревьев, Unity поддерживает хорошую производительность для рендеринга, так что вы можете иметь плотно засаженные леса с тысячами деревьев. Чтобы начать рисовать деревья, выберите Terrain на вкладке Hierarchy и на вкладке Inspector выберите пятую кнопку. Аналогично текстурам, необходимо также добавить деревья. Щелкните Edit Trees > Add Tree. Unity предложит вам префаб дерева, которое вы хотите использовать. Нажмите на маленький круг, и появится другое окно. На этот раз оно покажет вам все готовые префабы, которые у вас есть в вашем проекте. Выберите префаб дерева Broadleaf_desktop и нажмите Add. Это закроет окно prefab и добавит выбранное дерево в проект. Теперь вы можете выбрать пальму, чтобы нарисовать ее на своем ландшафте. В разделе Settings вы найдете несколько параметров, которые вы можете настроить, когда размещаете деревья в своей сцене. Brush Size определяет область, где вы будете рисовать, в то время как Tree Density определяет количество деревьев, которые вы будете иметь в нарисованной площади. Высокие значения будут означать больше деревьев. Tree Height позволит определить, как изменяется высота. Можно задать значение в произвольном порядке и использовать интервал значений, или задать определенное значения. Вы можете отключить параметр Lock Width to Height, чтобы сделать их одинаковыми. В разделе Lighting вы можете установить, как генерируются световые карты для ваших деревьев. Чтобы нарисовать деревья на поверхности, переместите указатель мыши на сцену. Синяя область представляет собой кисть. Если выбран тип дерева, нажмите левую кнопку мыши на поверхности и начните создавать деревья. Чтобы удалить деревья из определенной области, нажмите Shift и используйте левую кнопку мыши. Это очистит все деревья в области кисти. Если вы просто хотите стереть определенный тип дерева, удерживайте Control вместо Shift. Это очистит только выбранный тип дерева. Вы всегда можете изменить или удалить тип дерева, выбирая его и нажав кнопку Edit Trees. Чтобы изменить дерево, нажмите кнопку Edit Tree и, чтобы удалить его, нажмите кнопку Remove Tree. Наконец, вы заметите, что внутри компонента Terrain Collider у вас есть поле с именем Enable Tree Colliders. При выборе этого параметра можно включить коллизии между другими игровыми объектами и деревьями. Если вы не хотите вручную рисовать деревья, вы можете использовать кнопку Mass Place Trees. Если вы нажмете ее, появится новое окно. Затем Unity попросит вас создать несколько деревьев. Установите Number of Trees и нажмите Place. Затем Unity рандомно размещает деревья на поверхности. Следующий шаг – творческое заполнение ландшафта деревьями. Чтобы создать разные деревья, вы также можете добавить новые деревья, такие как Palm_Desktop, Broadleaf_Mobile и Conifer_Desktop. Для этого используйте параметр Edit Trees в меню Trees (на вкладке Inspector). Вы можете создать что-то вроде этого изображения (или что-то совершенно другое). Когда вы будете готовы, можете переходить к следующему шагу. Инструмент для создания других элементов Unity позволяет создавать траву и другие небольшие объекты, такие как камни, которые покрывают поверхность. Трава использованием двумерных изображений, а другие рендерится объекты с обычно являются стандартными мешами. Чтобы добавить детали в ландшафт, выберите свой ландшафтный объект из иерархии. На вкладке Inspector нажмите на шестую кнопку, ту, которая с цветами. Как можно видеть, у вас теперь есть аналогичный интерфейс, как и у Height Tools. Здесь также имеется набор кистей, которые можно выбрать, чтобы нарисовать список деталей. Поскольку вы не выбрали какие-либо детали объекта, добавим их, нажав Edit Details > Add Grass Texture. Откроется окно, в котором можно задать несколько свойств для травы. Detail Texture позволяет вам определить текстуру, которая будет использоваться для травы. Вы также можете установить несколько свойств, таких как Max Width, Min Width, Max Height, Min Height, Noise Spread, Healthy Color, Dry Color и Billboard. Все эти свойства определят, как будет выглядеть ваша трава. Для этого урока вы можете оставить параметры по умолчанию или изменить их по своему желанию. Нажмите на круг перед полем Detail Texture. Это откроет новое окно. Найдите GrassFrond01AlbedoAlpha, выберите его и нажмите Add. Как и для деревьев, вы можете использовать несколько кистей для рисования травы. Вы можете установить различные размеры Brush Sizes, изменить Opacity и Target Strength. Настало время быть креативным, и покрасить ландшафт травой. Если вы хотите добавить меши, чтобы нарисовать детали на вашем ландшафте, например камни, вам нужно повторить тот же процесс, что вы делали с импортом травы. Однако на этот раз при нажатии кнопки Edit Details выберите Add Detail Mesh. Откроется окно, где можно задать несколько параметров для мешей деталей, очень похожее на то, которое использовалась для импорта травы. К сожалению, ассеты окружающей среды не включают в себя префаб камень, поэтому вы не сможете сразу рисовать камни. Тем не менее, вы можете искать некоторые камни в Unity Asset Store, так как это отличное место для поиска бесплатных ассетов. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно для не пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Задание 1. Добавьте на него деревья, траву, камни и т.д. (не переусердствуйте, иначе сцена может зависать! Помните, вы разрабатываете прототип игрового приложения, которое в дальнейшем вы экспортируете для ПК). 7. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №4. Создание простой игры в 2D Unity 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по разработке полноценной 2D игры на Unity. Научиться работать с 2D графикой и спрайтами. 2. Теоретическая часть Организация проекта и импорт ресурсов После создания проекта, пришло время импортировать и упорядочить ассеты. Этот шаг еще раз очень важен для производительности. Основная организация проекта доступна на вкладке Project. Сейчас там почти пусто, за исключением папки Assets. Хотя этот шаг не является абсолютно необходимым пунктом, настоятельно рекомендуется вам организовывать ассеты интуитивно понятным способом, особенно если вы работаете с крупными проектами. Для начала создайте папки со следующими именами (щелкните правой кнопкой мыши Assets и выберите Create > Folder): Sprites Scripts Sounds Music Levels Теперь, когда вы создали папку проекта, пришло время импортировать игровые ресурсы (возьмите у преподавателя). Для импорта вам нужно только перетащить папку с ассетом в редактор Unity в папку, в которую требуется добавить этот конкретный ассет. Поэтому перейдите к файлу ресурсов, который вы только что загрузили, выберите содержимое папки Sprites и перетащите ее в папку Sprites в Unity. Затем редактор загрузит файлы. Повторите процесс для папок Music и Sounds; После того, как закончите, вы должны увидеть нечто подобное: Подготовка сцены для первого уровня После того, как мы подготовили редактор к работе и организовали проект, импортировали ресурсы, пришло время к созданию первого уровня. Unity работает со scenes (сценами). Сцены могут использоваться для хранения игровых объектов, меню, уровней или любых других игровых объектов. Интуитивный способ понять концепцию сцены - увидеть каждую сцену как индивидуальный уровень, где вы разместите ресурсы, создадите среду, врагов и т. д. С учетом вышесказанного, давайте создадим вашу первую сцену. По умолчанию при создании нового проекта Unity автоматически генерирует новую сцену. В этом случае сцена будет иметь только один объект, нашу Main Camera (основную камеру). Можно проверить объекты, которые имеются в сцене, на вкладке Hierarchy. Вы также можете использовать эту иерархию сцен для организации игровых объектов на вашей сцене. Обратите внимание: когда вы выбираете игровой объект на сцене, вы можете изменить его свойства на вкладке Inspector. Добавьте Sprite для фона уровня в качестве первого объекта: на вкладке Hierarchy нажмите Create > Sprite. Теперь измените имя на Background (нажмите клавишу Enter или сделайте это через первое поле вкладки Inspector). Обратите внимание, что поле Sprite в компоненте Sprite Renderer пустое. Это означает, что для этого объекта не был назначен спрайт. Давайте изменим это: перетащите элемент background1.png из папки Background в это поле. Затем текстура появится на сцене. Если вы перейдете на вкладку Game, вы сможете увидеть сцену в таком виде, какой она будет в финальной версии игры. Вы также можете изменить разрешение на этой вкладке. В этом уроке, у нас выбрано разрешения Standalone (1024x768) по-умолчанию (за исключением встроенных демо-приложений в которых разрешение несколько меньше.) Как вы видите, наш фон окружен синим цветом. Это связано с тем, что изображение не охватывает весь экран, поэтому нам придется масштабировать его. Во вкладке Inspector измените параметр Scale по оси X и Y на 4. Это приведет к тому, что фон будет покрывать всю игровую область. Кроме того, убедитесь, что в слое Order in Layer задано значение 0: при работе со спрайтами Unity использует слои для их прорисовки, это значит, чем ниже число, тем раньше будет рендериться спрайт, а спрайты с числами повыше, будут рисоваться поверх тех, что ниже. Так как объект Background это фон и он должен быть максимально отдаленным от нас, мы задаем этому параметру 0. Следующим шагом станет создание границ; мы добавим три спрайта (Top, Left и Right) - это будут стены игры. Добавьте три спрайта, используя тот же процесс, что и раньше, используйте для своих изображений ассеты bar1.png и bar2.png. Для того, чтобы настроить точное расположение и размеры барьеров, перейдите на вкладку Sceneпоиграйте с границами по отдельности. Не забудьте изменить Order in Layer на 1 для каждого спрайта. В итоге у вас должно получиться что-то подобное: Созданные нами границы будут стационарными объектами, и они будут вести себя одинаково, поэтому мы будем группировать их в один игровой объект. Для этого сначала создайте новый пустой игровой объект, щелкнув Game Object > Create Empty в верхней строке меню. Редактор создал новый пустой игровой объект на нашей сцене. Во вкладке Hierarchy перетащите три спрайта на пустой объект, который мы только что создали. Затем объекты границы станут подобъектами нового объекта. Переименуем объект в Bars для удобства, чтобы мы запомнили, что в нем. Осталось добавить шарик, платформу игрока и блоки. На данный момент мы добавим по одному каждого типа. Снова добавьте Sprite для каждого объекта и установите для параметра Order in Layer значение 1. Вот, что у вас должно получиться в итоге: Давайте сохраним текущую сцену в качестве первого уровня. Выберите File > Save Scene as..., назовем ее Level1 и переместим файл в папку Levels. Движение игрока У нас уже есть платформа игрока в интерфейсе; теперь мы должны взаимодействовать с ней. Она будет перемещаться по горизонтали, влево и вправо. Чтобы создать такое перемещение нам потребуется написать сценарий (Script). Сценарии представляют собой фрагменты программного кода, которые выполняют определенные задачи. Unity может работать с тремя языками программирования: Boo, JavaScript и C#. Все сценарии, созданные в этом уроке, будут написаны на языке C# (но при желании можно реализовать их на другом языке). Для создания сценария, перейдите на вкладку Project, выберите папку Scripts и кликните на ней правой кнопкой мыши, чтобы открыть меню. Выберите Create > C# Script. Появится новый файл NewBehaviourScript; переименуйте его в PlayerScript. На вкладке Inspector вы содержимое самого скрипта. увидите Дважды щелкните сценарий, чтобы отредактировать его. По умолчанию запуститься среда разработки MonoDevelop IDE, которую вы впоследствии можете изменить на любой удобный для вас редактор. using UnityEngine; using System.Collections; public class NewBehaviourScript : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } } Все сценарии Unity по умолчанию имеют два метода: Start(): используется для инициализации любых переменных или параметров, которые нам нужны в нашем коде. Update(): вызывается каждый кадр игры и поэтому необходим для обновления состояния игры. Для того, чтобы сдвинуть платформу игрока, нам потребуется два вида информации: позиция игрока скорость игрока Таким образом, создайте две переменные (глобальные переменные класса) для хранения этой информации: public float playerVelocity; private Vector3 playerPosition; Как вы могли заметить, playerVelocity является общедоступной переменной, а playerPosition - закрытой. Почему мы это сделали? Unity позволяет изменять значения общедоступных переменных внутри редактора без необходимости изменять фактический код; это очень полезно, когда у вас есть параметры, которые необходимо постоянно корректировать. Скорость платформы – одно из таких значений, и именно поэтому мы делаем ее общедоступной. Сохраните сценарий (в MonoDevelop) и снова перейдите в редактор Unity. Теперь у вас есть сценарий; вам просто нужно назначить его игровой платформе игрока. Выберите нашу платформу во вкладке Hierarchy и в окне Inspector добавьте компонент, кликнув на кнопку Add Component. Теперь введите имя скрипта, который вы только что сохранили, и добавьте его игровому объекту. Другой способ добавить скрипт к компоненту - перетащить его из своей папки в область кнопки Add Component. Вы должны увидеть что-то подобное во вкладке Inspector: Как вы можете видеть, поскольку мы оставили переменную playerVelocity общедоступной, теперь можно установить ее значение в редакторе. На данный момент установите значение 0.3 и вернитесь к коду. Теперь вы инициализируете playerPosition. Для этого вам нужно получить доступ к позиции игрового объекта в методе запуска скрипта Start: // Use this for initialization void Start () { // get the initial position of the game object playerPosition = gameObject.transform.position; } Теперь мы определили начальное положение и скорость платформы, но нам все равно придется двигать ее. Для этого мы отредактируем метод Update. Так как нам надо, чтобы платформа перемещалась только горизонтально, мы можем использовать метод GetAxis класса Input для определения направления игрока по горизонтальной оси (-1 влево, +1вправо), умножив полученное число на скорость и прибавив эту величину к текущей горизонтальной позиции игрока playerPosition, мы и получим движение. Пока мы имеем дело с вводом, мы также хотим убедиться, что игра завершается, когда игрок нажимает клавишу Esc. Ниже приведен полный фрагмент кода: using UnityEngine; using System.Collections; public class PlayerScript : MonoBehaviour { public float playerVelocity; private Vector3 playerPosition; // Use this for initialization void Start () { // get the initial position of the game object playerPosition = gameObject.transform.position; } // Update is called once per frame void Update () { // horizontal movement playerPosition.x += Input.GetAxis ("Horizontal") * playerVelocity; // leave the game if (Input.GetKeyDown(KeyCode.Escape)){ Application.Quit(); } // update the game object transform transform.position = playerPosition; } } Сохраните сценарий и вернитесь в редактор Unity. Теперь нажмите кнопку Play и попробуйте передвинуть платформу при помощи стрелок «влево» и «вправо». Определение игровой области Вероятно, вы заметили, что платформа может перемещаться за пределы уровня. Это происходит потому, что для игрового пространства нет границ. Чтобы создать границу, сначала создайте другую общедоступную переменную - назовите ее boundary (граница). Эта переменная будет хранить максимальную позицию X, к которой может перемещаться платформа. Поскольку мы собираемся построить уровень в симметричной форме вокруг точки с координатами (0, 0, 0), это означает, что абсолютное граничное значение переменной boundary будет одинаковым и для положительной части оси X, и для отрицательной. Чтобы не позволить игроку пересечь границу, мы добавим несколько условий if. В принципе, мы скажем, что если значение Х позиции больше граничного значения, тогда значение Х будет установлено равным границе. Таким образом, мы гарантируем, что платформа никогда не покинет зону игры. Соответствующий код приведен ниже: using UnityEngine; using System.Collections; public class PlayerScript : MonoBehaviour { public float playerVelocity; private Vector3 playerPosition; public float boundary; // Use this for initialization void Start () { // get the initial position of the game object playerPosition = gameObject.transform.position; } // Update is called once per frame void Update () { // horizontal movement playerPosition.x += Input.GetAxis("Horizontal") * playerVelocity; // leave the game if (Input.GetKeyDown(KeyCode.Escape)){ Application.Quit(); } // update the game object transform transform.position = playerPosition; // boundaries if (playerPosition.x < -boundary) { transform.position = new Vector3 (-boundary, playerPosition.y, playerPosition.z); } if (playerPosition.x > boundary) { transform.position = new Vector3(boundary, playerPosition.y, playerPosition.z); } } } Теперь вернитесь в редактор и найдите наилучшее значение для переменной boundary. Передвигая положение платформы по оси X, можно увидеть, что идеальное значение равно 5.46 (по крайней мере, в нашем проекте). Откройте Inspector и сбросьте позицию платформы по оси X на 0, и введите значение 5.46 в параметр Boundary в компоненте Player Script. Нажмите кнопку Play в редакторе. Теперь можно перемещать платформу, но только внутри игрового пространства. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно для не пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Задание 1. Используя выданные вам ассеты повторите шаги лабораторной работы, изменяя игровое поле и объекты, под выданные вам ассеты. 7. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №5. Создание простой 2D игры на Unity (физика и механика) 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по разработке полноценной 2D игры на Unity. Научиться работать с 2D графикой и спрайтами. 2. Теоретическая часть Создание свойств физики В этой конкретной игре нам нужно создать физические свойства для трех компонентов: платформы, мячика и стен. Поскольку мы создаем 2Dигру, мы будем использовать и применять 2D-коллайдеры. (Коллайдер - это особый тип компонента, который позволяет объекту реагировать на коллайдеры других объектов.) Начните с добавления коллайдера (столкновения) к нашей платформе. В окне Hierarchy выберите нашу платформу. Перейдите во вкладку Inspector, нажмите Add Component и введите collider. Как вы можете видеть на скриншоте ниже, вам доступны несколько типов коллайдеров. Каждый отдельный коллайдер имеет определенные свойства, соответствующие связанным объектам. Поскольку наша платформа имеет прямоугольную форму, мы будем использовать Box Collider 2D. Выберите его, и компонент будет автоматически добавлен к вашему игровому объекту. Значения размера и центрального положения коллайдера уже определены; Эти значения будут работать по умолчанию, поэтому их не нужно менять. Теперь сделаем тот же процесс для трех границ и блока. (Hierarchy > Inspector > Add Component > Box Collider 2D). Все ваши игровые объекты теперь имеют коллайдеры, кроме мячика. Поскольку мячик имеет другую форму, вам придется использовать другой коллайдер. Выберите его, и на вкладке Inspector добавьте компонент Circle Collider 2D. Компонент Circle Collider 2D похож на Box Collider, за исключением того, что вместо параметра Size, который определяет ширину и высоту поля, он имеет параметр Radius, который определяет радиус круга. Материал для отскока Чтобы заставить мяч отскакивать, нам нужно создать упругий физический материал и прикрепить его к этому мячику. В Unity уже создан конкретный материал, поэтому нам просто нужно его добавить. Во вкладке Project создайте новую папку внутри папки Asset и назовите ее Physics. Выберите эту папку, нажмите Create и выберите Physics2D Material. BallPhysicsMaterial. Назовите свой новый физический материал Материал имеет два параметра: Friction (трение) и Bounciness(упругость). Если вам требуется абсолютно упругое тело, то следует изменить значения на: 0 для Friction, и 1 для Bounciness. Теперь, когда вы подготовили материал, примените его к мячику. Выберите игровой объект ball (мяч) на вкладке Hierarchy и перейдите на вкладку Inspector. Если вы поближе познакомитесь с компонентом Circle Collider 2D, вы заметите, что он имеет параметр Material; здесь вы можете прикрепить любой физический материал, который требуется для этого объекта. Чтобы прикрепить материал BallPhysicsMaterial, просто выберите его и перетащите в параметр Material на коллайдере. Добавление компонента Rigid Body Для того, чтобы мяч двигался под контролем физики, нам нужно добавить еще одну вещь: компонент rigidbody. Выберите объект мяч и добавьте компонент RigidBody 2D. Этот компонент имеет несколько параметров, которые можно задать. Поскольку мячик будет перемещаться только с помощью отскока, вы должны изменить параметр Gravity Scale с 1 на 0 - таким образом, мы гарантируем, что на мяч не влияет гравитация. Остальные параметры можно оставить по умолчанию: Программирование поведения мяча Мяч будет полностью динамичным, поэтому нам нужно создать скрипт для этого поведения. Создайте новый скрипт (мы снова будем использовать C#) и назовите его BallScript. Назначьте новый скрипт объекту мяч (Hierarchy > Inspector > Add Component). Теперь давайте проанализируем правила и свойства мячика, прежде чем начнем писать скрипт: Мяч должен иметь два состояния: неактивное (следует за платформой до начала игры) и активное (отскакивает от платформы, стен и блоков). Мяч станет активным только после того, как игрок нажмет конкретную клавишу на клавиатуре. Когда мяч становится активным, мы применяем к нему силу, чтобы он начал движение. Если мяч вышел за пределы игрового поля, он должен снова помещаться на платформу. Основываясь на этой информации, мы сначала создадим глобальные переменные ballIsActive, ballPosition и ballInitialForce. private bool ballIsActive; private Vector3 ballPosition; private Vector2 ballInitialForce; Теперь, когда у нас есть переменные, мы должны инициализировать игровой объект. В методе Start мы должны: Создать силу, чтобы толкать мяч. Установить мяч в неактивное состояние. Сохранить положение мяча. Вот как это выглядит: void Start () { // create the force ballInitialForce = new Vector2 (100.0f,300.0f); // set to inactive ballIsActive = false; // ball position ballPosition = transform.position; } Здесь мы применяем силу 300 по оси Y, чтобы мяч двигался вверх, а 100вдоль оси X, чтобы мячик двигался по диагонали, а не прямо вверх. Таким образом, вы вынуждаете игрока перемещать платформу. В методе Update мы определим поведение мячика. Давайте рассмотрим это в каждом конкретном случае. Во-первых, мы должны обрабатывать вводимые пользователем данные; Мы воспользуемся стандартной кнопкой действия в Unity - Jump. Клавиша, ассоциирующаяся с Jump, может быть изменена, но по умолчанию используется Space (пробел) на клавиатуре. void Update () { // check for user input if (Input.GetButtonDown ("Jump") == true) { } } Следующее, что нужно сделать, это проверить состояние мяча, так как клавиша действия должна работать только тогда, когда мяч неактивен: void Update () { // check for user input if (Input.GetButtonDown ("Jump") == true) { // check if is the first play if (!ballIsActive){ } } } Предположим, что это начало игры, так что мы должны применить силу к мячу и установить его в активное состояние: Новый метод Update должен выглядеть следующим образом: void Update () { // check for user input if (Input.GetButtonDown ("Jump") == true) { // check if is the first play if (!ballIsActive){ // add a force rigidbody2D.AddForce(ballInitialForce); // set ball active ballIsActive = !ballIsActive; } } } Теперь запустите проект нажав Play и протестируйте действие Jump; Вы заметите, что мяч отталкивается и начинает прыгать вокруг так, как он и должен. Тем не менее вы также заметите, что мяч не следует за положением платформы, когда неактивен. Остановите игру и давайте это изменим. В методе Update мы должны проверить состояние мячика и, если мячик неактивен, мы должны убедиться, что значение по оси X мячика совпадает со значением по оси X платформы. А как мы можем получить доступ к положению игрока, если оно находится в совсем другом игровом объекте? Просто: мы создаем переменную игрового объекта и храним ссылку на объект платформы. Итак, добавьте объект платформы переменной типа GameObject: private bool ballIsActive; private Vector3 ballPosition; private Vector2 ballInitialForce; // GameObject public GameObject playerObject; в качестве общедоступной глобальной Вернемся к методу Update. Мы проверим состояние мяча и ссылку на платформу. Если состояние неактивно и объект платформа не null (то есть, у нас есть ссылка на него), мяч должен следовать за положением платформы. Завершенный метод Update: void Update () { // check for user input if (Input.GetButtonDown ("Jump") == true) { // check if is the first play if (!ballIsActive){ // add a force rigidbody2D.AddForce(ballInitialForce); // set ball active ballIsActive = !ballIsActive; } } if (!ballIsActive && playerObject != null){ // get and use the player position ballPosition.x = playerObject.transform.position.x; // apply player X position to the ball transform.position = ballPosition; } } Сохраните сценарий и вернитесь в редактор. Как вы, возможно, заметили, ссылка на платформу является общедоступной, это означает, что вы передаете ее в редактор. На вкладке Hierarchy выберите мяч. На вкладке Inspector вы заметите, что параметр Player Object в нашем скрипте в настоящее время отсутствует None. Чтобы сделать эту ссылку на платформу игрока, просто перетащите игровой объект платформа из вкладки Hierarchy в поле Player Object в компоненте скрипт. Нажмите кнопку Play и протестируйте свою игру. Теперь вы увидите, что мяч будет следовать за игроком до нажатия клавиши Jump. Сброс игры Для завершения скрипта вам нужно сделать еще одну вещь. Как вы могли заметить, если игрок не поймает мяч, и он упадет за пределы поля, то сброс игры не происходит. Давайте модифицируем метод Update, чтобы исправить это. Мы проверим, активен ли мяч и если его положение по оси Y меньше 6. Если это так, мы установим мяч неактивным и сбросим положение мяча в положение игрока. Этот фрагмент выглядит следующим образом: if (ballIsActive && transform.position.y < -6) { ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; } Если вы сохраните скрипт и проверите в редакторе, вы увидите, что каждый раз, когда мяч падает с экрана, положение мяча перемещается в положение игрока и устанавливается в неактивное состояние. Однако, если вы начнете играть, вы заметите странное поведение. Каждый раз, когда мяч падает, при следующем нажатии клавиши действия увеличивается его скорость. Почему так происходит? Ну, помните, что мы добавляем силы к мячику при запуске, так что каждый раз, когда вы сбрасываете игру, вы продолжаете добавлять силы к жесткому телу, делая игру безумно трудной сразу после нескольких попыток. Итак, вопрос в том, как нам это решить? Чтобы сохранить одну и ту же общую силу, необходимо убедиться, что все силы, примененные к мячику, все время сбрасываются. Для этого мы можем просто активировать параметр Is Kinematic каждый раз, когда мяч останавливается, и деактивировать его при запуске игры. Этот параметр определяет, влияет ли физика на мяч, и его отключение гарантирует, что все силы, примененные до этого, исчезнут. Для этого добавьте в метод Update еще две строки: rigidbody2D.isKinematic = false перед добавлением силы и rigidbody2D.isKinematic = true, когда мы хотим, чтобы мяч снова начал двигаться. В конце концов, итоговый метод Update должен выглядеть следующим образом: public class BallScript : MonoBehaviour { private bool ballIsActive; private Vector3 ballPosition; private Vector2 ballInitialForce; // GameObject public GameObject playerObject; // Use this for initialization void Start () { // create the force ballInitialForce = new Vector2 (100.0f,300.0f); // set to inactive ballIsActive = false; // ball position ballPosition = transform.position; } // Update is called once per frame void Update () { // check for user input if (Input.GetButtonDown ("Jump") == true) { // check if is the first play if (!ballIsActive){ // reset the force rigidbody2D.isKinematic = false; // add a force rigidbody2D.AddForce(ballInitialForce); // set ball active ballIsActive = !ballIsActive; } } if (!ballIsActive && playerObject != null){ // get and use the player position ballPosition.x = playerObject.transform.position.x; // apply player X position to the ball transform.position = ballPosition; } // Check if ball falls if (ballIsActive && transform.position.y < -6) { ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; rigidbody2D.isKinematic = true; } } } Теперь можно нажать кнопку Play и проверить все вышеперечисленные функции. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно для не пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 7. Задание 1. Используя выданные вам ассеты повторите шаги лабораторной работы, изменяя игровое поле и объекты, под выданные вам ассеты. 8. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №6. Создание простой 2D игры в Unity (скриптинг и публикация) 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по разработке полноценной 2D игры на Unity. Научиться работать с 2D графикой и спрайтами.. 2. Теоретическая часть Скрипт для блока Сейчас у нас готова вся базовая механика игры. Не определено только поведение блоков. Поскольку блоки являются важной частью игры, мы должны создать для них отдельный скрипт. Скрипт для блока должен содержать информацию о: Общее количество ударов, которое может выдержать блок; Очки, которые получит игрок при уничтожении блока. (Обратите внимание, что количество ударов и очков может меняться в соответствии с цветом блока.) Исходя из этого, давайте выделим три переменные для блока: Переменная для хранения количества выдерживаемых ударов. Переменная для хранения количества очков, которые заработает игрок при уничтожении этого блока. Переменная для хранения количества уже принятых на себя ударов. Первые две переменные будут public, чтобы мы могли изменять их значения в редакторе Unity. Третья будет private, поскольку предназначена только для внутреннего пользования. Таким образом, создайте новый скрипт BlockScript. Определите эти переменные и инициализируйте количество ударов равным 0: public class BlockScript : MonoBehaviour { public int hitsToKill: public int points; private int numberOfHits; // Use this for initialization void Start () { numberOfHits = 0; } // Update is called once per frame void Update () { } } Следующий шаг - определить, когда шарик попал в блок. Когда это столкновение происходит, мы проверяем, достаточное ли было количество ударов, чтобы его уничтожить, или он все еще не поврежден. Для этого мы можем использовать специальный метод OnCollisionEnter2D, который вызывается каждый раз, когда происходит столкновение с вашим объектом. Для того, чтобы воспользоваться этой функцией, мы должны пометить мячик специальным тегом. В редакторе Unity на вкладке Hierarchy выберите мячик, перейдите в окно Inspector и найдите поле Tag. В верхней части вкладки Inspector, прямо под именем игрового объекта, есть поле Tag, которое в настоящее время определено как Untagged. Нажмите кнопку, и выпадающее меню появится с различными возможностями тегов: Нам нужен конкретный тег для мяча, поэтому нажмите Add Tag, чтобы создать новый тег. После нажатия этой опции появляется новый интерфейс: Cвойство Element 0 определят название тега, поэтому введите в него имя Ball. Теперь, когда у вас есть новый тег Ball, измените тег объекта мячик на Ball. Откройте файл BlockScript, чтобы мы могли переопределить метод OnCollisionEnter2D. Чтобы определить игровой объект мячик, проверьте, тег игрового объекта Ball; если это так, то столкновение было между блоком и мячом. Добавьте в свой скрипт следующий код. void OnCollisionEnter2D(Collision2D collision){ if (collision.gameObject.tag == "Ball"){ } } Теперь мы можем обнаружить столкновение мяча и блока. При каждом таком столкновении мы будем увеличивать на единицу переменную, отвечающую за количество уже сделанных ударов, если эта переменная станет равной максимальному количеству ударов, которое выдерживает блок, то мы смело уничтожим этот блок. Для этого мы можем использовать метод Destroy. Обновленный метод OnCollisionEnter2D выглядит следующим образом: void OnCollisionEnter2D(Collision2D collision){ if (collision.gameObject.tag == "Ball"){ numberOfHits++; if (numberOfHits == hitsToKill){ // destroy the object Destroy(this.gameObject); } } } А теперь добавьте этот скрипт BlockScript к объекту Block (Hierarchy > Inspector > Add Component): Пришло время проверить, что все в порядке. Измените значение Hits To Kill в редакторе на 1 и запустите Play игру. Когда мяч попадает в блок, блок должен исчезнуть. Создание префабов Теперь, когда механики блока готовы, мы будем заполнять наш уровень. Поскольку вы будете использовать несколько блоков, это подходящее время для создания префабов в Unity. Prefab (Префаб) - это один из типов объектов, предназначений для многократного использования, который можно вставлять несколько раз в одну и ту же сцену. Это означает, что, если вы хотите, например, изменить значение очков для синих блоков, вам не нужно делать это для каждого синего блока на сцене. Если у вас есть Prefab синего блока, вы просто корректируете значение Prefab, и все блоки на сцене будут обновлены. Чтобы создать Prefab для синих блоков, начните с переименования объекта Block в Blue Block. Затем создайте новую папку в папке «Assets» под названием Prefabs. Теперь перетащите объект Blue Blocks внутрь новой папки. Как вы могли заметить, иконка кубика в верхней части вкладки Inspector теперь стала синего цвета. Также, как и название блока во вкладке Hierarchy. Это значит, что был создан префаб. Довольно просто, не так ли? Отныне, выбрав этот префаб и изменив у него какое-либо значение, обновятся параметры у всех его экземпляров. Чтобы проверить префаб, перетащите его из папки на вкладку Hierarchy. Как видите, теперь у нас два синих блока, но они оба находятся на одной и той же позиции. Для того, чтобы два блока находились на разных позициях, выберите один из них на вкладке Hierarchy и переместите его на сцене в другое положение. Таким нехитрым образом вы изменили позицию одного конкретного экземпляра, а не всех синих блоков. Нажмите кнопку Play и протестируйте работу префабов. Пересоздание префабов Теперь вы создадите оставшиеся префабы для других блоков (зеленого, желтого и красного). Основные шаги, которые нужно выполнить для каждого из них: 1. Создайте новый спрайт. 2. Добавьте соответствующее изображение. 3. Добавляем компонент Box Collider 2D. 4. Добавьте BlockScript. 5. Переименуйте объект. 6. Создайте префаб В конце концов мы должны создать четыре различных префаба (по одному для каждого типа блока): Для того, чтобы игра была более интересной, измените количество ударов для уничтожения блока (параметр Hits To Kill) таким образом: Синий: 1 удар. Зеленый: 2 удара. Желтый: 3 удара. Красный: 4 удара. Добавьте несколько различных блоков на сцену и запустите игру нажав Play, убедитесь, что все работает как ожидалось. Дизайн уровней Настало время создать свой первый уровень. Используя префабы, заполните область игры несколькими блоками. Если вы разместили столько блоков, сколько вы сделали, вкладка Hierarchy, вероятно, переполнена игровыми объектами! Чтобы ваш проект был хорошо организован, давайте создадим пустые игровые объекты для четырех типов блоков, а затем сгруппируем блоки по цвету: На данный момент ваша игра почти готова, ваша основная механика реализована, и она должна выглядеть примерно так: Система очков и жизней Система очков и жизней - это один из способов протестировать игроков и ввести новую динамику в игру. На данный момент ваша игра не имеет никакого способа для игроков прогрессировать или проигрывать. Давайте исправим это сейчас. Откройте PlayerScript, созданный на прошлом уроке, и добавьте две переменные: количество набранных очков и число оставшихся жизней. Игрок будет начинать игру с тремя жизнями и без очков: private int playerLives; private int playerPoints; // Use this for initialization void Start () { // get the initial position of the game object playerPosition = gameObject.transform.position; playerLives = 3; playerPoints = 0; } Нам нужен метод, увеличивающий количество очков, которые игрок получает каждый раз, когда он уничтожает блок. Создайте для этого новый метод addPoints: void addPoints(int points){ playerPoints += points; } Теперь у нас есть новый метод, ожидающий значения, но как он его получит? Слишком много блоков, чтобы ссылаться на игровой объект платформа в каждом... Лучшим способом является передача сообщения от блока платформе. Как это сделать? Для начала выберем для платформы тег Player (Hierarchy > Inspector > Tag): Теперь, когда платформа имеет свой тег, перейдем к скрипту блока BlockScript, где изменим метод OnCollisionEnter2D отправив очки игровому объекту: до того, как он будет уничтожен, мы найдем нашу платформу при помощи тега Player используя метод FindGameObjectsWithTag; это приведет к возврату массива совпадающего объекта, так как есть только один объект с этим тегом, мы знаем, что объект в позиции 0 возвращаемого массива представляет собой игровой объект платформа. Теперь, когда у вас есть ссылка на игровой объект, вы можете отправить ему сообщение с помощью метода SendMessage. При этом вы можете вызвать конкретный метод игрового объекта - в этом случае - метод addPoints. Следующий фрагмент показывает нам, как все это работает: void OnCollisionEnter2D(Collision2D collision){ if (collision.gameObject.tag == "Ball"){ numberOfHits++; if (numberOfHits == hitsToKill){ // get reference of player object GameObject player = GameObject.FindGameObjectsWithTag("Player")[0]; // send message player.SendMessage("addPoints", points); // destroy the object Destroy(this.gameObject); } } } Следующее, что нам нужно сделать, это отредактировать префабы и указать конкретные значения очков для каждого типа блока. Вы можете использовать следующие значения: Синий: 10 очков; Зеленый: 20 очков; Желтый: 35 очков; Красный: 50 очков; Теперь нам нужно показать в интерфейсе игры количество жизней и набранные очки. В скрипте PlayerScript создайте метод OnGUI. Этот метод представит GUI графический интерфейс вашей игры; это один из основных способов представления информации в игровом пространстве. (Обратите внимание на символы, чувствительные к регистру). Чтобы добавить очки и жизни, нам нужно создать Label с нужным текстом. В PlayerScript добавьте метод OnGUI и создайте в нем этот Label: void OnGUI(){ GUI.Label (new Rect(5.0f,3.0f,200.0f,200.0f),"Live's: " + playerLives + " playerPoints); Score: " + } Теперь вы можете нажать Play и играть в игру, вы увидите очки и жизни в верхней левой части экрана. Тем не менее, вы еще не запрограммировали отображение жизней и точек для их обновления! Используя тот же PlayerScript, добавьте следующий метод TakeLife. Метод будет вычитать только одну жизнь игрока каждый раз, когда он вызывается: void TakeLife(){ playerLives--; } Наконец, перейдите к BallScript, и в разделе, где вы проверяете, если мячик падает за пределы игрового поля, вызовем метод TakeLife для отправки сообщения игровому объекту. Полный фрагмент представлен ниже: // Check if ball falls if (ballIsActive && transform.position.y < -6) { ballIsActive = !ballIsActive; ballPosition.x = playerObject.transform.position.x; ballPosition.y = -4.2f; transform.position = ballPosition; rigidbody2D.isKinematic = true; // New code - Send Message playerObject.SendMessage("TakeLife"); } Запустите игру и проверьте, что все работает правильно. Звуки и музыка В предыдущей лабораторной работе вы импортировали в проект несколько звуковых файлов. Теперь пришло время их использовать. В папке Sounds есть три файла: hit.wav: используется при каждом столкновении с мячиком. lose.wav: используется, когда игрок теряет жизнь. point.wav: используется, когда игрок получает очки. Чтобы эти звуки проигрывались, нам нужно будет немножко изменить наши скрипты Player и Ball. Начнем с объекта Ball (мячик). Первоначально нам нужно добавить аудио компонент к игровым объектам. Выберите мяч и добавьте Audio Source (Hierarchy > Inspector > Add Component). Обратите внимание, что вы должны снять флажок Play On Awake, если он установлен; иначе звук автоматически будет проигрываться при запуске сцены. У вас есть аудио компонент; теперь вам нужно изменить скрипт для взаимодействия с самим компонентом. Создайте новую переменную для звукового файла. Поскольку вы хотите получить доступ к звуку в редакторе, переменная должна быть общедоступной public: public AudioClip hitSound; Так как мы хотим, чтобы звук проигрывался каждый раз, когда мячик сталкивается с чем-то активным. Мы используем метод OnCollisionEnter2D, который проверяет активность мячика, если он в активном состоянии тогда воспроизводится звук. void OnCollisionEnter2D(Collision2D collision){ if (ballIsActive) { audio.PlayOneShot (hitSound); } } Обратите внимание на условие проверки активности мячика. Если мяч не будет в активном состоянии (а это значит, что он будет лежать на платформе), то без этого условия звук проигрывался бы всегда. Теперь перейдите в редактор и убедитесь, что в компоненте Ball Script есть новый параметр Hit Sound. Перетащите файл hit.wav со вкладки Project в поле Hit Sound. Вы должны увидеть что-то вроде этого: Нажмите кнопку Play и проверьте, воспроизводится ли звук каждый раз, когда мячик сталкивается с чем-нибудь. А теперь давайте добавим два других звука в игру. Вставьте новый компонент Audio Source, но теперь уже на объект платформы. Снова снимите флажок с пункта Play On Awake. Откройте переменные скрипт для PlayerScript звука. Первая и создайте переменная две дополнительные предназначена для воспроизведения звука, когда игрок набирает очки, а вторая отвечает за то, что игрок потерял одну жизнь. Обе они должны быть объявлены как public переменные. public AudioClip pointSound; public AudioClip lifeSound; Поскольку теперь у вас есть объекты, давайте модифицируем метод addPoints для воспроизведения звука каждый раз, когда он вызывается. Как и прежде, вы должны вызвать метод PlayOneShot из объекта audio: void addPoints(int points){ playerPoints += points; audio.PlayOneShot (pointSound); } Теперь сделайте то же самое в методе TakeLife: void TakeLife(){ playerLives--; audio.PlayOneShot (lifeSound); } Сохраните сценарий и перейдите еще раз в редактор. Перетащите в каждое из полей по звуковому файлу (point.wav и lose.wav). Вы должны увидеть что-то вроде того, что на скриншоте: Запустите игру нажав кнопку Play и удостоверьтесь в том, что все три звуковых эффекта работают правильно. Фоновая музыка Несмотря на добавленные нами звуковые эффекты, возникает ощущение, что игра какая-то совершенно пустая. Давайте изменим это, добавив фоновую музыку, которая отличается для каждого уровня. Во вкладке Hierarchy найдите объект Background и добавьте Audio Source: Теперь перетащите файл Jaunty Gumption.mp3 из окна Project в поле Audio Clip компонента Audio Source. На этот раз вы должны оставить параметр Play On Awake включенным, так как мы хотим, чтобы музыка начала воспроизводиться при загрузке нашего уровня. Также включите параметр Loop, который позволит музыке начаться заново, если она закончится. Действуйте и запустите игру нажав Play и проверьте работу фоновой музыки. Теперь в вашей игре есть звук и музыка. Уровни Чтобы закончить игру, мы решим две вещи: Когда игрок уничтожает все блоки, он должен перейти на следующий уровень. Когда игрок теряет все свои жизни, игра должна перезапуститься. Начнем с создания второго уровня для игры. Вместо того, чтобы создавать уровень с нуля, мы можем просто дублировать первый уровень и изменить объекты этого нового уровня. Для этого вам просто нужно сохранить вашу сцену как новую. Нажмите File > Save Scene as..., назовите этот уровень Level2 и поместите его в папку Levels. Чтобы этот уровень отличался от первого, в идеале следует изменить расположение всех блоков. Здесь все ограничивается вашей фантазией, но мы поменяем лишь фоновое изображение и музыку. Выберите объект Background в окне Hierarchy и посмотрите на вкладку Inspector. Перетащите файл Background2 Sprites\Backgrounds в поле Sprite игрового объекта Background: из папки Для изменения фоновой музыки вам нужно перетащить нужный музыкальный файл в параметр Audio Clip. Для второго уровня Level 2 используйте файл Monkeys Spinning Monkeys.mp3. Если вы нажмете кнопку Play, вы можете протестировать этот новый уровень. Как вы можете видеть, он работает точно так же, как и первый, но с другим фоном и другой музыкой. Поскольку второй уровень готов, настало время разобраться с двумя описанными ранее ситуациями. Откройте скрипт платформы и создайте новый метод WinLose. Здесь мы будем проверять, потерял ли игрок все свои жизни: если переменная playerLives будет равна 0, мы попросту вызовем метод Application.LoadLevel и перезапустим первый уровень. void WinLose(){ // restart the game if (playerLives == 0) { Application.LoadLevel("Level1"); } } Далее нам следует проработать момент, когда все блоки на сцене будут уничтожены. Чтобы определить количество оставшихся блоков, мы снова можем использовать метод FindGameObjectsWithTag, на этот раз ищем объекты на текущем уровне с тегом Block. Если полученный массив имеет длину 0, то мы знаем, что пришло время загрузить следующий уровень. Поскольку у нас всего лишь два уровня, то если игрок выиграет второй уровень, мы просто закроем игру (вызвав Application.Quit). Полный фрагмент кода метода WinLose: void WinLose(){ // restart the game if (playerLives == 0) { Application.LoadLevel("Level1"); } // blocks destroyed if ((GameObject.FindGameObjectsWithTag ("Block")).Length == 0) { // check the current level if (Application.loadedLevelName == "Level1") { Application.LoadLevel("Level2"); } else { Application.Quit(); } } } В скрипте PlayerScript мы будем вызывать метод WinLose в методе Update- просто добавьте его в конец метода. Для простоты, завершенный метод Update: void Update () { // horizontal movement playerPosition.x += Input.GetAxis("Horizontal") * playerVelocity; // leave the game if (Input.GetKeyDown(KeyCode.Escape)){ Application.Quit(); } // update the game object transform transform.position = playerPosition; // boundaries if (playerPosition.x < -boundary) { transform.position = new Vector3 (-boundary, playerPosition.y, playerPosition.z); } if (playerPosition.x > boundary) { transform.position = new Vector3(boundary, playerPosition.y, playerPosition.z); } // Check game state WinLose (); } Вернитесь в редактор. Для того, чтобы метод WinLose работал правильно, нам надо пометить блоки тегом. Перейдите во вкладку Project, откройте папку Prefabs и выберите блок. Все блоки в настоящее время не отмечены, и нет тега Block, поэтому мы должны его создать. Нажмите кнопку Tag и выберите опцию Add Tag. Добавьте новый тег Block: Теперь игра готова к тестированию. Нажмите Play и попробуйте! Компиляция и развертывание проекта Компиляция и развертывание, как правило, являются последними шагами в разработке проекта. В этом разделе вы узнаете, как создать окончательную сборку и необходимые конфигурации для ее запуска в кроссплатформенной среде. Во-первых, вам нужно добавить все сцены в сборку. Нажмите File > Build Settings. Появится новое окно, где, скорее всего, Scenes In Build будет пустым, как здесь: Если это так, вам нужно добавить сцены, которые мы создали ранее. Нажмите Add Current, и сцена будет добавлена в область Scenes In Build: В нашем примере мы добавили первый уровень. Закройте это окно и откройте в редакторе второй уровень. Нажмите снова File > Build Settings и нажмите еще раз Add Current: Если вы добавили второй уровень до первого, не волнуйтесь: просто поменяйте их местами при помощи мыши (так как первая сцена в этом списке - это та, которая будет загружена при запуске игры). После того, как оба уровня добавлены в правильном порядке, нажмите на кнопку Build and Run, и вы должны увидеть окончательную версию вашей игры. Как вы могли заметить, Unity поддерживает множество платформ, которые вы можете выбрать для развертывания своей игры, а именно: Веб-браузеры ПК, Mac и Linux Мобильные операционные системы: iOS, Android, Blackberry и Windows Phone 8 Google Native Client Консоли: Xbox 360, PS3 и Wii Windows Store Большим преимуществом использования движка Unity является то, что, написав код однажды, вы можете быстро и легко развернуть ваше приложение на любой из вышеупомянутых платформ. Однако следует отметить, что некоторые платформы и операционные системы имеют определенные ограничения в отношении правил развертывания. Например, вы не сможете установить ваше приложение на iOS, если у вас нет компьютера на Mac OS и лицензии разработчика. Вам также нужны лицензии для развертывания игры на PS3 и Xbox. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно не для пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Задание 1. Используя выданные вам ассеты повторите шаги лабораторной работы, изменяя игровое поле и объекты, под выданные вам ассеты. 7. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №7. Создание дорог в Unity 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по созданию дорог в Unity. 2. Теоретическая часть Для создания дорог в Unity существует большое количество плагинов. В лабораторной работе создание дороги рассматривается на примере плагина EasyRoads3D Free, который вы предварительно должны скачать и установить из Assets Store. Добавьте ландшафт на игровой уровень. Можете использовать наработки из предыдущих лабораторных работ. Добавьте новую сеть дорог выбрав в меню Main Menu > GameObject > 3D Object > EasyRoads3D > New Road Network Новый игровой объект "Road Network" будет создан и выбран в дереве сцены. В инспекторе свойств вы увидите панель инструментов: Давайте рассмотрим ее подробнее. Статус сцены Эта вкладка отображает свойства выбранной дороги/соединения/пересечения. Добавление новой дороги Активируйте вкладку для добавления новой дороги. Вы можете выбрать тип дороги из выпадающего списка. Тип дороги влияет на ее ширину и материал. После нажатия на кнопку "Add new Object" новая дорога будет создана в дереве сцены. Теперь вы можете начать добавлять узлы дороги нажатием shift+ЛКМ на ландшафте. Дорога прокладывается между двумя узлами. Добавление префаба пересечения На этой вкладке отображаются все доступные пересечения/соединения дорог. Добавление производится аналогично. Построение ландшафта Вкладка открывает настройки управления ландшафтом для подстройки ландшафта под форму дороги. Общие настройки Настройки обочины Вкладка открывает настройки обочины дорог. Справка/информация Создание дороги Для создания новой дороги, нажмите на вкладку . Выберите preset road из выпадающего списка и нажмите Add New Object. Новая дорога будет создана в объекте Road Network / Road Objects 1) Нажмите SHIFT и щелкните мышкой в сцене на ландшафте, чтобы добавить новый узел дороги. Дорога будет автоматически создаваться между двумя узлами. Нажатие мышкой в сцене снимет выделение дороги. Нажатие на узлы дороги выделит дорогу. 2) Узлы дороги могут быть вставлены между двумя другими перемещением мыши на место нового узла и нажатием клавиши I. 3) Узлы могут быть удалены нажатием клавиши R. 4) Вы можете изменить положение узла выделив его, и перемещая как обычный игровой объект (клавиша W и M). 5) Вы можете выделять несколько узлов дороги. Для того чтобы воспользоваться вкладкой закончить построение дорог вы можете из панели инструментов. Нажмите Build Terrain(s) и Finalize. После этого ландшафт подстроится под дороги, а дороги станут обычными объектами. Внимание! После выполнения этих шагов вы не сможете редактировать сеть дорог! 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно для не пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Задание 1. Разработайте игровой уровень с ландшафтом, дорогами, дополнительными объектами (можете использовать Assets Store). 7. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №8. Добавление автомобиля в Unity 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по работе с префабами, ассетами и AssetsStore. 2. Теоретическая часть Создание простого автомобиля в Unity. 1. Итак создадим четыре пустых объекта для удобной иерархии в нашем объекте: carRoot – контейнер для всех элементов машины (геометрия, свет, камеры, объекты для скриптов) car – контейнер для объектов именно машины, physic – контейнер для физических моделей колес, graphic – графические объекты. 2. Добавим в carRoot камеру. 3. В car добавляем компонент RigidBody, его масса – это масса корпуса машины, она будет влиять на устойчивость и на то, насколько сильно он прижимает колеса. Для того чтобы на поворотах нас не сильно заносило, и при падении машина возвращалась в правильное положение, а не переворачивалась, нам потребуется два изменения – компонент ConstantForce в car, который будет прижимать машину на поворотах, кроме того, переместим центр массы машины вниз, добавив на нее скрипт carControl с кодом вроде этого: gameObject.GetComponent(Rigidbody).centerOfMass = Vector3 (0, высота_машинки*масштаб, 0); 4. В physic создаем пустой объект body с компонентом CapsuleCollider – это будет простой корпус машины, обтекаемый и не дающий застревать в стенках. 5. создаем пустой объект wheel_BL и добавляем ему компонент WheelCollider, и настраиваем его: Center – расположение колеса, Radius – радиус колеса, Suspension Distance – длинна пружин подвески. Suspension Spring : Spring – сила пружины подвески, чем выше тем сильнее пружинит, Suspension Spring : Damper – сила амортизатора, делает более плавным движение пружины. Mass – масса колес, опять же влияет на поведение на заносах, прыжках. Теперь добавим в объект wheel_BL простой цилиндрический меш, чтобы так сказать, иметь отладочную версию, впрочем, можно ограничится тем, что Unity нам и так предоставляет. 6. Клонируем наше колесо до нужного числа, например, 4 – в принципе, машинка уже готова. Теперь нам нужно только заставить колеса вращаться с ускорением по нажатию клавиш и поворачиваться, что можно сделать например так: var WheelRight:GameObject; var WheelLeft:GameObject; var BackWheels:boolean; var BackFront:boolean; var WheelSpeed:float; var WheelRpmMax:float; private var WheelRotateAngle = 20; gameObject.GetComponent(Rigidbody).centerOfMass = Vector3 (0, -0.6*2.3, 0); function FixedUpdate() { if (Input.GetKeyDown ("w")) { WheelRight.GetComponent (WheelCollider).motorTorque = WheelSpeed; WheelLeft.GetComponent (WheelCollider).motorTorque = WheelSpeed; } if (Input.GetKeyUp("w")) { WheelRight.GetComponent (WheelCollider).motorTorque = 0; WheelLeft.GetComponent (WheelCollider).motorTorque = 0; } if (Input.GetKeyDown ("s")) { WheelRight.GetComponent (WheelCollider).motorTorque = -WheelSpeed; WheelLeft.GetComponent (WheelCollider).motorTorque = -WheelSpeed; } if (Input.GetKeyUp("s")) { WheelRight.GetComponent (WheelCollider).motorTorque = 0; WheelLeft.GetComponent (WheelCollider).motorTorque = 0; } if (Input.GetKeyDown ("a")) { if(BackWheels){ WheelRight.transform.Rotate(0,-WheelRotateAngle,0); WheelLeft.transform.Rotate(0,-WheelRotateAngle,0); }else{ WheelRight.transform.Rotate(0,WheelRotateAngle,0); WheelLeft.transform.Rotate(0,WheelRotateAngle,0); } } if (Input.GetKeyUp ("a")) { if(BackWheels){ WheelRight.transform.Rotate(0,WheelRotateAngle,0); WheelLeft.transform.Rotate(0,WheelRotateAngle,0); }else{ WheelRight.transform.Rotate(0,-WheelRotateAngle,0); WheelLeft.transform.Rotate(0,-WheelRotateAngle,0); } } if (Input.GetKeyDown ("d")) { if(BackWheels){ WheelRight.transform.Rotate(0,WheelRotateAngle,0); WheelLeft.transform.Rotate(0,WheelRotateAngle,0); }else{ WheelRight.transform.Rotate(0,-WheelRotateAngle,0); WheelLeft.transform.Rotate(0,-WheelRotateAngle,0); } } if (Input.GetKeyUp ("d")) { if(BackWheels){ WheelRight.transform.Rotate(0,-WheelRotateAngle,0); WheelLeft.transform.Rotate(0,-WheelRotateAngle,0); }else{ WheelRight.transform.Rotate(0,WheelRotateAngle,0); WheelLeft.transform.Rotate(0,WheelRotateAngle,0); } } } 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно для не пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 6. Задание 1. Модифицируйте предыдущую лабораторную работу добавив в нее автомобиль. 2. Украсьте игровой уровень различными объектами (препятствиями, бордюрами, отбойниками и т.п.) 7. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем. Лабораторная работа №9. Работа со звуком в Unity 1. Цель и содержание Цель лаботаторной работы: получить знания и навыки по работе со звуком в Unity. 2. Теоретическая часть В прошло лабораторной работе мы импортировали в проект несколько звуковых файлов. Пришло время их использовать. В папке Sounds находятся три файла: hit.wav: используется при каждом ударе шарика; lose.wav: используется, когда игрок теряет жизнь; point.wav: используется, когда игрок получает очки. Чтобы звуки проигрывались, нам нужно будет немножко изменить наши скрипты. Но прежде, чем это делать, следует добавить компонент аудио. Начнем, пожалуй, с шарика. Итак, выберите объект шарика и добавьте Audio Source (Hierarchy -> Inspector -> Add Component). Обратите внимание — при добавлении компонента вы должны снять флажок Play On Awake, иначе звук автоматически будет проигрываться при запуске игры. Итак, компонент добавлен. Настало время изменить скрипт. Откройте его и создайте новую переменную для звукового файла: public AudioClip hitSound; Так как мы хотим, чтобы звук проигрывался каждый раз, когда мячик врезается во что-либо, то метод воспроизведения звука добавим в функцию проверки коллизии: void OnCollisionEnter2D(Collision2D collision){ if (ballIsActive) { audio.PlayOneShot (hitSound); } } Обратите внимание на условие проверки активности шарика. Если мяч не будет в активном состоянии (а это значит, что он будет лежать на платформе), то без этого условия звук проигрывался бы всегда. Перейдите в редактор и убедитесь, что в компоненте Ball Script есть поле Hit Sound. Перетащите звуковой файл hit.wav из окна Project на поле Hit Sound. После этого вы должны увидеть нечто такое: Нажмите кнопку Play и проверьте, воспроизводится ли звук каждый раз, когда мячик сталкивается с чем-нибудь. А теперь давайте добавим два других звука. Вставьте новый компонент Audio Source, но теперь уже на объект платформы. Не забудьте снять флажок с пункта Play On Awake. Откройте скрипт и создайте две одинаковые переменные для звука. Первый будет отвечать за звук, который означает, что игрок заработал некоторое количество очков, а второй — за то, что игрок потерял одну жизнь. Обе переменные, как и в первом случае, будут объявлены публично для того, чтобы их можно было задать из редактора Unity: public public AudioClip lifeSound; AudioClip pointSound; Отлично. А теперь откроем метод addPoints и изменим его. Для единовременного проигрывания звука, вам нужно обратиться к методу PlayOneShot объекта audio: void addPoints(int points){ playerPoints += points; audio.PlayOneShot (pointSound); } Аналогично поступим и с методом TakeLife: void TakeLife(){ playerLives--; audio.PlayOneShot (lifeSound); } Сохраните проделанные изменения и перейдите в основной редактор. У компонента Player Script объекта Player есть два неназначенных поля (это только что созданные нами переменные). Перетащите в каждое из полей по звуковому файлу (point.wav и lose.wav): Запустите игру и удостоверьтесь в том, что все три звуковых эффекта работают правильно. Фоновая музыка Несмотря на добавленные нами звуковые эффекты, складывается ощущение, что игра какая-то тихая, пустая. Давайте добавим фоновую музыку — для каждого уровня свою. Во вкладке Hierarchy найдите объект Background и добавьте Audio Source: Теперь перетащите файл Jaunty Gumption.mp3 из поле Audio Clip компонента Audio Source. На этот окна Project на раз оставьте параметр Play On Awake включенным для того, чтобы фоновая музыка играла сразу при загрузке уровня. Также включите параметр Loop, который позволит музыке начаться заново, если она закончится. Запустите игру и проверьте работу фоновой музыки. Уровни Для того, чтобы игра закончилась, требуется: уничтожить все блоки, после чего игра должна перейти на следующий уровень; потерять все свои жизни, после чего игра должна перезапустить текущий уровень. Давайте создадим по крайней мере еще один уровень, чтобы мы могли перенаправлять туда игрока, если он завершит первый. Вместо того, чтобы создавать его с нуля, мы можем скопировать первый уровень и немножко видоизменить его. Чтобы сделать это, вы должны сохранить текущую сцену как другую. Выберите File -> Save Scene as…, назовите новую сцену Level2 и поместите его в папку Levels. Для того, чтобы созданный уровень отличался от второго, в идеале следует изменить расположение блоков. Здесь все ограничивается вашей фантазией, но мы поменяем лишь фоновые изображение и музыку. Выберите объект Background в окне Hierarchy и посмотрите на вкладку Inspector. У компонента Sprite Renderer есть поле Sprite. Перетащите туда другое папки Sprites/Backgrounds. изображение — background2.jpg из Чтобы изменить фоновую музыку, вам достаточно перенести на поле Audio Clip новую музыку. Используйте файл Monkeys Spinning Monkeys.mp3. Если вы нажмете на кнопку Play, то сможете потестировать новый уровень: он работает точно так же, как и первый, но с другими фоновыми картинкой и музыкой. Итак, второй уровень готов. Откройте скрипт платформы и добавьте новый метод WinLose. Здесь мы будем проверять, потерял ли все свои жизни переменная playerLives будет равна 0, мы игрок. попросту Если вызовем метод Application.LoadLevel и перезапустим текущий уровень. void WinLose(){ // перезапускаем уровень if (playerLives == 0) { Application.LoadLevel("Level1"); } } Далее нам следует обработать момент, когда все блоки на сцене будут уничтожены. Сделать это можно при помощи знакомой нам функции FindGameObjectsWithTag, которая вернет массив объектов. Если же длина массива будет равна 0, значит блоков у нас не осталось и мы переходим на следующий уровень. Кстати, т.к. у нас всего лишь два уровня, то если игрок прошел второй — мы попросту выйдем из игры, вызвав метод Application.Quit: void WinLose(){ // перезапускаем уровень if (playerLives == 0) { Application.LoadLevel("Level1"); } // все блоки уничтожены if ((GameObject.FindGameObjectsWithTag ("Block")).Length == 0) { // проверяем текущий уровень if (Application.loadedLevelName == "Level1") { Application.LoadLevel("Level2"); } else { Application.Quit(); } } } Вызывать данный метод мы будем в функции Update: void Update () { // горизонтальное движение playerPosition.x += Input.GetAxis ("Horizontal") * playerVelocity; // выход из игры if (Input.GetKeyDown(KeyCode.Escape)){ Application.Quit(); } // обновим позицию платформы transform.position = playerPosition; // проверка выхода за границы if (playerPosition.x < -boundary) { transform.position = new Vector3 (-boundary, playerPosition.y, playerPosition.z); } if (playerPosition.x > boundary) { transform.position = new Vector3(boundary, playerPosition.y, playerPosition.z); } //проверка состояния игры WinLose(); } Вернитесь обратно в редактор Unity. Для того, чтобы метод WinLose работал правильно, нам надо пометить блоки тегом. Перейдите в окно Project, откройте папку Prefabs и выберите блок. Сейчас нет тега Block, поэтому вы должны кликнуть на кнопку Tag и выбрать Add Tag. Добавьте новый тег под названием Block: Запустите игру и протестируйте, работают ли переходы между уровнями. Компиляция и развертывание Итак, мы подошли к последней стадии в разработке нашей маленькой игры. Нажмите File -> Build Settings. Появится новое окно, где, скорее всего, Scenes In Build будет пустым, как здесь: Если у вас это окно выглядит также, то вы должны добавить ваши сцены в сборку. Нажмите Add Current и добавится текущая. Закройте это окно и откройте в редакторе второй уровень. Затем аналогичным образом добавьте сцену в сборку. Если в окне вы видите первую сцену после второй — не волнуйтесь. Просто поменяйте их местами при помощи мыши. В противном случае игра запустится со второго уровня. А теперь нажмите на кнопку Build and Run, и вы должны увидеть окончательную версию вашей игры. Как вы могли заметить, Unity поддерживает множество платформ: Веб-браузеры Windows, Mac, Linux iOS, Android, Blackberry, Windows Phone 8 Google Native Client Xbox 360, PS3, Wii Windows Store Большим преимуществом этого движка является то, что написав код однажды, вы можете развернуть ваше приложение на любой из вышеупомянутых платформах. Тем не менее, ограничения, все же, имеются. Например, вы не сможете установить ваше приложение на iOS, если у вас нет компьютера на Mac OS и лицензии iOS-разработчика. Из-за отсутствия лицензии разработчика развернуть приложения для консолей вы также не сможете. 3. Аппаратура и материалы Для выполнения лабораторной работы рекомендуется использовать персональный компьютер со следующими характеристиками: 32-разрядный (x86) или 64-разрядный (x64) процессор с тактовой частотой 1,5 ГГц и выше, оперативная память – 1 Гб и выше, свободное дисковое пространство – не менее 1 Гб, графическое устройство DirectX 9. Программное обеспечение: операционная система на базе WINDOWS, Microsoft Visual Studio 2008 и старше. 4. Указания по технике безопасности Техника безопасности при выполнении лабораторной работы совпадает с общепринятой Самостоятельно не для пользователей производить ремонт персональных компьютеров. персонального компьютера, установку и удаление программного обеспечения; в случае неисправности персонального компьютера сообщить об этом обслуживающему персоналу лаборатории (оператору, администратору); соблюдать правила техники безопасности при работе с электрооборудованием; не касаться электрических розеток металлическими предметами; рабочее место пользователя персонального компьютера должно содержаться в чистоте; не разрешается возле персонального компьютера принимать пищу, напитки. 5. Содержание отчета и его форма 1. Номер и название лабораторной работы. 2. Цели лабораторной работы. 3. Ответы на контрольные вопросы. 4. Экранные формы, показывающие порядок выполнения лабораторной работы, и результаты, полученные в ходе её выполнения: Отчет о выполнении лабораторной работы в письменном виде сдается преподавателю. 7. Задание 1. Повторите пример из лабораторной работы добавив в ваши предыдущие лабораторные работы, выданные вам звуки. 8. Защита работы Перед выполнением лабораторной работы каждый студент получает индивидуальное задание. Защита лабораторной работы происходит только после его выполнения (индивидуального задания). При защите лабораторной работы студент: 1) отвечает на контрольные вопросы; 2) поясняет ход выполнения индивидуального задания; 3) поясняет результаты, полученные в результате выполнения индивидуального задания. Ход защиты лабораторной работы контролируется преподавателем.