
- •Предисловие
- •Введение
- •Благодарности
- •О книге
- •Перспективы
- •Условные обозначения, требования и доступные для скачивания данные
- •Автор в Интернете
- •Об авторе
- •Глава 1. Знакомство с Unity
- •1.1. Достоинства Unity
- •1.1.1. Сильные стороны и преимущества Unity
- •1.1.2. Недостатки, о которых нужно знать
- •1.1.3. Примеры игр на основе Unity
- •1.2. Как работать с Unity
- •1.2.1. Вкладка Scene, вкладка Game и панель инструментов
- •1.2.2. Работа с мышью и клавиатурой
- •1.2.3. Вкладка Hierarchy и панель Inspector
- •1.2.4. Вкладки Project и Console
- •1.3. Готовимся программировать в Unity
- •1.3.1. Запуск кода в Unity: компоненты сценария
- •1.3.2. Программа MonoDevelop — межплатформенная среда разработки
- •1.4. Заключение
- •Глава 2. Создание 3D-ролика
- •2.1. Подготовка…
- •2.1.1. Планирование проекта
- •2.1.2. Трехмерное координатное пространство
- •2.2. Начало проекта: размещение объектов
- •2.2.1. Декорации: пол, внешние и внутренние стены
- •2.2.2. Источники света и камеры
- •2.2.3. Коллайдер и точка наблюдения игрока
- •2.3. Двигаем объекты: сценарий, активирующий преобразования
- •2.3.1. Схема программирования движения
- •2.3.2. Написание кода
- •2.3.3. Локальные и глобальные координаты
- •2.4. Компонент сценария для осмотра сцены: MouseLook
- •2.4.1. Горизонтальное вращение, следящее за указателем мыши
- •2.4.2. Поворот по вертикали с ограничениями
- •2.4.3. Одновременные горизонтальное и вертикальное вращения
- •2.5. Компонент для клавиатурного ввода
- •2.5.1. Реакция на нажатие клавиш
- •2.5.2. Независимая от скорости работы компьютера скорость перемещений
- •2.5.4. Ходить, а не летать
- •2.6. Заключение
- •3.1. Стрельба путем бросания лучей
- •3.1.1. Что такое бросание лучей?
- •3.1.2. Имитация стрельбы командой ScreenPointToRay
- •3.1.3. Добавление визуальных индикаторов для прицеливания и попаданий
- •3.2. Создаем активные цели
- •3.2.1. Определяем точку попадания
- •3.2.2. Уведомляем цель о попадании
- •3.3. Базовый искусственный интеллект для перемещения по сцене
- •3.3.1. Диаграмма работы базового искусственного интеллекта
- •3.3.2. «Поиск» препятствий методом бросания лучей
- •3.3.3. Слежение за состоянием персонажа
- •3.4.1. Что такое шаблон экземпляров?
- •3.4.2. Создание шаблона врага
- •3.4.3. Экземпляры невидимого компонента SceneController
- •3.5. Стрельба путем создания экземпляров
- •3.5.1. Шаблон снаряда
- •3.5.2. Стрельба и столкновение с целью
- •3.5.3. Повреждение игрока
- •3.6. Заключение
- •Глава 4. Работа с графикой
- •4.1. Основные сведения о графических ресурсах
- •4.2. Создание геометрической модели сцены
- •4.2.1. Назначение геометрической модели
- •4.2.2. Рисуем план уровня
- •4.2.3. Расставляем примитивы в соответствии с планом
- •4.3. Наложение текстур
- •4.3.1. Выбор формата файла
- •4.3.2. Импорт файла изображения
- •4.3.3. Назначение текстуры
- •4.4. Создание неба с помощью текстур
- •4.4.1. Что такое скайбокс?
- •4.4.2. Создание нового материала для скайбокса
- •4.5. Собственные трехмерные модели
- •4.5.1. Выбор формата файла
- •4.5.2. Экспорт и импорт модели
- •4.6. Системы частиц
- •4.6.1. Редактирование параметров эффекта
- •4.6.2. Новая текстура для пламени
- •4.6.3. Присоединение эффектов частиц к трехмерным объектам
- •4.7. Заключение
- •5.1. Подготовка к работе с двухмерной графикой
- •5.1.1. Подготовка проекта
- •5.1.2. Отображение двухмерных изображений (спрайтов)
- •5.1.3. Переключение камеры в режим 2D
- •5.2. Создание карт и превращение их в интерактивные объекты
- •5.2.1. Создание объекта из спрайтов
- •5.2.2. Код ввода с помощью мыши
- •5.2.3. Открытие карты по щелчку
- •5.3. Отображение различных карт
- •5.3.1. Программная загрузка изображений
- •5.3.3. Создание экземпляров карт
- •5.3.4. Тасуем карты
- •5.4. Совпадения и подсчет очков
- •5.4.1. Сохранение и сравнение открытых карт
- •5.4.2. Скрытие несовпадающих карт
- •5.4.3. Текстовое отображение счета
- •5.5. Кнопка Restart
- •5.5.1. Добавление к компоненту UIButton метода SendMessage
- •5.5.2. Вызов метода LoadLevel в сценарии SceneController
- •5.6. Заключение
- •Глава 6. Двухмерный GUI для трехмерной игры
- •6.1. Перед тем как писать код…
- •6.1.1. IMGUI или усовершенствованный 2D-интерфейс?
- •6.1.2. Выбор компоновки
- •6.1.3. Импорт изображений UI
- •6.2. Настройка GUI
- •6.2.1. Холст для интерфейса
- •6.2.2. Кнопки, изображения и текстовые подписи
- •6.2.3. Управление положением элементов UI
- •6.3. Программирование интерактивного UI
- •6.3.1. Программирование невидимого объекта UIController
- •6.3.2. Создание всплывающего окна
- •6.3.3. Задание значений с помощью ползунка и поля ввода
- •6.4. Обновление игры в ответ на события
- •6.4.1. Интегрирование системы сообщений
- •6.4.2. Рассылка и слушание сообщений сцены
- •6.4.3. Рассылка и слушание сообщений проекционного дисплея
- •6.5. Заключение
- •7.1. Корректировка положения камеры
- •7.1.1. Импорт персонажа
- •7.1.2. Добавление в сцену теней
- •7.1.3. Облет камеры вокруг персонажа
- •7.2. Элементы управления движением, связанные с камерой
- •7.2.1. Поворот персонажа лицом в направлении движения
- •7.2.2. Движение вперед в выбранном направлении
- •7.3. Выполнение прыжков
- •7.3.1. Добавление вертикальной скорости и ускорения
- •7.3.2. Распознавание поверхности с учетом краев и склонов
- •7.4. Анимация персонажа
- •7.4.1. Создание анимационных клипов для импортированной модели
- •7.4.2. Создание контроллера для анимационных клипов
- •7.4.3. Код, управляющий контроллером-аниматором
- •7.5. Заключение
- •8.1. Создание дверей и других устройств
- •8.1.1. Открывание и закрывание дверей
- •8.1.2. Проверка расстояния и направления перед открытием двери
- •8.1.3. Управление меняющим цвет монитором
- •8.2. Взаимодействие с объектами путем столкновений
- •8.2.1. Столкновение с препятствиями, обладающими физическими свойствами
- •8.2.2. Управление дверью с помощью триггера
- •8.2.3. Сбор разбросанных по игровому уровню элементов
- •8.3. Управление инвентаризационными данными и состоянием игры
- •8.3.1. Настраиваем диспетчеры игрока и инвентаря
- •8.3.2. Программирование диспетчеров
- •8.3.3. Сохранение инвентаря в виде коллекции: списки и словари
- •8.4. Интерфейс для использования и подготовки элементов
- •8.4.1. Отображение элементов инвентаря в UI
- •8.4.2. Подготовка ключа для открытия двери
- •8.4.3. Восстановление здоровья персонажа
- •8.5. Заключение
- •9.1. Создание натурной сцены
- •9.1.1. Генерирование неба с помощью скайбокса
- •9.1.2. Настройка управляемой кодом атмосферы
- •9.2. Скачивание сводки погоды из Интернета
- •9.2.1. Запрос веб-данных через сопрограмму
- •9.2.2. Парсинг текста в формате XML
- •9.2.3. Парсинг текста в формате JSON
- •9.2.4. Изменение вида сцены на базе данных о погоде
- •9.3. Добавление рекламного щита
- •9.3.1. Загрузка изображений из Интернета
- •9.3.2. Вывод изображения на щите
- •9.3.3. Кэширование скачанного изображения
- •9.4. Отправка данных на веб-сервер
- •9.4.1. Слежение за погодой: отправка запросов POST
- •9.4.2. Серверный код в PHP-сценарии
- •9.5. Заключение
- •Глава 10. Звуковые эффекты и музыка
- •10.1. Импорт звуковых эффектов
- •10.1.1. Поддерживаемые форматы файлов
- •10.1.2. Импорт аудиофайлов
- •10.2. Воспроизведение звуковых эффектов
- •10.2.1. Система воспроизведения: клипы, источник, подписчик
- •10.2.2. Присваивание зацикленного звука
- •10.2.3. Активация звуковых эффектов из кода
- •10.3. Интерфейс управления звуком
- •10.3.1. Настройка центрального диспетчера управления звуком
- •10.3.2. UI для управления громкостью
- •10.3.3. Воспроизведение звуков UI
- •10.4. Фоновая музыка
- •10.4.1. Воспроизведение музыкальных циклов
- •10.4.2. Отдельная регулировка громкости
- •10.4.3. Переход между песнями
- •10.5. Заключение
- •Глава 11. Объединение фрагментов в готовую игру
- •11.1. Построение ролевого боевика изменением назначения проектов
- •11.1.1. Сборка ресурсов и кода из разных проектов
- •11.1.2. Элементы наведения и щелчка
- •11.1.3. Замена старого GUI новым
- •11.2. Разработка общей игровой структуры
- •11.2.1. Управление ходом миссии и набором уровней
- •11.2.2. Завершение уровня
- •11.2.3. Проигрыш уровня
- •11.3. Обработка хода игры
- •11.3.1. Сохранение и загрузка достижений игрока
- •11.3.2. Победа в игре при прохождении всех уровней
- •11.4. Заключение
- •Глава 12. Развертывание игр на устройствах игроков
- •12.1. Создание приложений для настольных компьютеров: Windows, Mac и Linux
- •12.1.1. Построение приложения
- •12.1.2. Настройки проигрывателя: имя и значок приложения
- •12.1.3. Компиляция в зависимости от платформы
- •12.2. Создание игр для Интернета
- •12.2.1. Проигрыватель Unity и HTML5/WebGL
- •12.2.2. Создание файла Unity и тестовой веб-страницы
- •12.2.3. Обмен данными с JavaScript в браузере
- •12.3. Сборки для мобильных устройств: iOS и Android
- •12.3.1. Настройка инструментов сборки
- •12.3.2. Сжатие текстур
- •12.3.3. Разработка подключаемых модулей
- •12.4. Заключение
- •Приложение А. Перемещение по сцене и клавиатурные комбинации
- •А.1. Навигация с помощью мыши
- •А.2. Распространенные клавиатурные комбинации
- •Б.1. Инструменты программирования
- •Б.1.1. Visual Studio
- •Б.1.2. Xcode
- •Б.1.3. Android SDK
- •Б.1.4. SVN, Git или Mercurial
- •Б.2. Приложения для работы с трехмерной графикой
- •Б.2.1. Maya
- •Б.2.3. Blender
- •Б.3. Редакторы двухмерной графики
- •Б.3.1. Photoshop
- •Б.3.2. GIMP
- •Б.3.3. TexturePacker
- •Б.4. Звуковое программное обеспечение
- •Б.4.1. Pro Tools
- •Б.4.2. Audacity
- •Приложение В. Моделирование скамейки в программе Blender
- •В.1. Создание сеточной геометрии
- •В.2. Назначение материала

5.5. Кнопка Restart 133
if (_firstRevealed.id == _secondRevealed.id) {
_score++; |
Отображаемый текст — это задаваемое |
scoreLabel.text = "Score: " + _score; ¬ |
|
} |
свойство текстовых объектов. |
|
|
... |
|
Как видите, текст представляет собой свойство объекта, которому вы можете назначить новую строку. Перетащите расположенный в сцене текст на только что добавленную к компоненту SceneController переменную и щелкните на кнопке Play. После этого в процессе игры вы будете видеть, как при каждом следующем совпадении ваш счет увеличивается. Ура, наша игра работает!
5.5. Кнопка Restart
Наша игра Memory стала полнофункциональной. В нее уже можно играть. Отсутствует только один элемент, который рано или поздно потребуется любому игроку. Дело в том, что сейчас мы можем сыграть всего одну партию; после этого нужно будет выйти из игры и загрузить ее снова. Добавим на экран элемент управления, позволяющий игрокам начинать все заново без перезагрузки.
Для этого нужно решить две задачи: создать UI-кнопку и запрограммировать перезагрузку игры по щелчку на этой кнопке. После этого игра должна выглядеть так, как показано на рис. 5.11.
Рис. 5.11. Готовая игра Memory вместе с кнопкой Start
Кстати, ни одна из этих задач не относится к особенностям исключительно двухмерных игр; во всех играх требуется пользовательский интерфейс с кнопками, и все игры нуждаются в возможности перезагрузки. Именно решением этих задач мы закончим главу.
5.5.1. Добавление к компоненту UIButton метода SendMessage
Первым делом поместите в сцену спрайт с изображением кнопки, перетащив его с вкладки Project. Поместите его в точку с координатами 4.5, 3.25, –10; в результате изображение кнопки окажется в верхнем правом углу (то есть сместится на 450 пикселов

134 Глава 5. Игра Memory на основе новой 2D-функциональности
вправо и на 325 пикселов вверх) и подвинется ближе к камере, чтобы отобразиться поверх остальных игровых объектов. Так как нам нужна реакция этого объекта на щелчок мыши, добавьте к нему коллайдер (так же, как вы это делали с картами, щелкните на кнопке Add Component и выберите в разделе Physics 2D вариант Box Collider).
ПРИМЕЧАНИЕ Как уже было сказано в предыдущем разделе, Unity поддерживает разные механизмы создания UI-элементов, к которым относится и усовершенствованная система пользовательских интерфейсов, появившаяся в последних версиях Unity. Сейчас мы ограничимся созданием кнопки из стандартных экранных объектов. А вот следующая глава познакомит вас с усовершенствованной UI-функциональностью; мы изучим пользовательские интерфейсы для двухмерных и трехмерных игр, идеально встроенные в данную систему.
Создайте сценарий UIButton.cs, код которого показан в следующем листинге, и назначьте его объекту, изображающему кнопку.
Листинг 5.13. Создание кнопки многократного воспроизведения
using UnityEngine;
using System.Collections;
public class UIButton : MonoBehaviour |
{ |
Ссылка на целевой объект |
|
[SerializeField] private GameObject |
targetObject; ¬ |
||
для информирования о щелчках. |
|||
[SerializeField] private string targetMessage; |
|
public Color highlightColor = Color.cyan;
public void OnMouseOver() {
SpriteRenderer sprite = GetComponent<SpriteRenderer>(); if (sprite != null) {
sprite.color = highlightColor; ¬ Меняем цвет кнопки при наведении на нее указателя мыши.
}
}
public void OnMouseExit() {
SpriteRenderer sprite = GetComponent<SpriteRenderer>(); if (sprite != null) {
sprite.color = Color.white;
}
}
public void OnMouseDown() {
transform.localScale = new Vector3(1.1f, 1.1f, 1.1f); ¬ В момент щелчка размер кнопки |
|
} |
слегка увеличивается. |
|
|
public void OnMouseUp() { |
|
transform.localScale = Vector3.one; |
|
if (targetObject != null) { |
Отправка сообщения целевому объекту |
targetObject.SendMessage(targetMessage); ¬ |
|
} |
в момент щелчка на кнопке. |
|
}
}
Основная часть кода выполняется внутри набора функций вида OnMouseЧтоТо; подобно методам Start() и Update(), этот набор функций автоматически доступен всем компонентам сценариев в Unity. С функцией MouseDown вы уже встречались в разделе 5.2.2. Все эти функции в случае объектов, снабженных коллайдером, отвечают на

5.5. Кнопка Restart 135
взаимодействия с мышью. Функции MouseOver и MouseExit представляют собой пару событий, возникающих при наведении на объект указателя мыши: первое — в момент, когда указатель впервые появляется над объектом, а второе — когда он убирается с объекта. Аналогично, функции MouseDown и MouseUp являются парой событий, возникающих в момент щелчка. Первое событие генерируется при физическом нажатии кнопки, второе — при ее отпускании.
Легко заметить, что при наведении указателя мыши на спрайт кнопки цвет этого спрайта слегка меняется, а в момент щелчка меняется еще и его размер. В обоих случаях вы видите, что эти изменения (цвета или масштаба) возникают после начала взаимодействия с мышью, затем свойство возвращается в исходное состояние (к белому цвету или единичному масштабу). Для масштабирования в коде используется стандартный компонент transform, присутствующий у всех объектов GameObject. А вот для изменения цвета применен компонент SpriteRenderer, присущий таким объектам, как спрайты; спрайту присваивается цвет, определенный в редакторе Unity при помощи общедоступной переменной.
В момент отпускания кнопки мыши происходит не только возвращение масштаба к единичному значению, но и вызов метода SendMessage(). Этот метод вызывает функцию с указанным именем во всех компонентах рассматриваемого объекта GameObject. Как целевой объект для рассылки, так и отправляемое сообщение определены через сериализованные переменные. Такой подход позволяет использовать один и тот же компонент UIButton для всех видов кнопок. Достаточно на панели Inspector сопоставить цели в виде различных кнопок разным объектам.
Обычно при написании программ на таком сильно типизированном языке, как C#, для взаимодействия с целевым объектом нужно знать его тип (к примеру, для вызова открытого метода объекта: целевой-объект.SendMessage()). Но сценарии для UI-элементов могут содержать множество различных типов целевых объектов, поэтому в Unity метод SendMessage() позволяет отправлять таким объектам заданные сообщения, даже если вы не знаете их тип.
ВНИМАНИЕ Метод SendMessage() менее рационально использует ресурсы процессора, чем открытые методы, вызываемые для известных типов (имеются в виду конструкции object. SendMessage(«Метод») вместо component.Method()), поэтому пользуйтесь этим методом только в случаях, когда это значительно упрощает понимание кода и работу с ним. Как правило, это ситуация, когда сообщение адресуется большому количеству объектов различных типов; в таких ситуациях отсутствие гибкости наследования или даже интерфейсов будет мешать процессу разработки игры и затруднять эксперименты.
Написав код, выполните связывание общедоступных переменных кнопки на панели Inspector. Выберите по своему вкусу цвет выделения (хотя заданный по умолчанию бирюзовый вполне подходит к синей кнопке). Кроме того, перетащите объект SceneController на ячейку целевого объекта и введите в поле для сообщения слово
Restart.
Если теперь запустить игру, в верхнем правом углу игрового поля появится кнопка перезагрузки, меняющая цвет при наведении на нее указателя мыши и слегка выступающая в момент щелчка на ней. Но результатом щелчка станет сообщение об