- •Предисловие
- •Введение
- •Благодарности
- •О книге
- •Перспективы
- •Условные обозначения, требования и доступные для скачивания данные
- •Автор в Интернете
- •Об авторе
- •Глава 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. Назначение материала
238 Глава 9. Подключение игры к Интернету
объявленную в момент вызова метода из сценария WebLoadingBillboard. Обратите внимание на синтаксис объявления лямбда-функции: () => {}.
Реализация обратного вызова в виде отдельной функции не только дала возможность вызвать метод в сценарии WebLoadingBillboard; именно лямбда-функция сохраняет локальную копию скачанного изображения. В итоге методу GetWebImage() достаточно скачать изображение один раз; во всех последующих вызовах будет использоваться уже локальная копия.
Так как данная оптимизация применяется к последующим вызовам, ее эффект появится только при наличии нескольких рекламных щитов. Давайте сделаем копию щита, чтобы в сцене появилась хотя бы пара объектов. Выделите щит, выберите команду Duplicate (в меню Edit или в меню, вызываемом щелчком правой кнопки мыши) и переместите копию в сторону (например, измените координату X на 18).
Запустите игру и посмотрите, что получилось. В управлении первым щитом отмечается значительная пауза, связанная со скачиванием изображения из Интернета. Зато при подходе ко второму щиту изображение появляется сразу же, ведь оно уже загружено.
Это важная оптимизация процесса скачивания изображений (именно поэтому у браузеров режим кэширования графики включен по умолчанию). Теперь у нас осталась всего одна задача, с решением которой я хочу вас познакомить: отправка данных на сервер.
9.4. Отправка данных на веб-сервер
Мы рассмотрели несколько примеров скачивания данных, но пока ни разу не выполняли обратный процесс. Для выполнения заданий в этом разделе вам потребуется сервер, на который будут отправляться данные. Если возможность доступа к серверу у вас отсутствует, раздел можно просто пропустить. Кроме того, желающие могут легко скачать ПО с открытым исходным кодом и настроить тестовый сервер. Я рекомендую для этой цели сервер XAMPP. Для его скачивания посетите страницу https:// www.apachefriends.org/ru/index.html. После установки у вас появился доступ к папке htdocs с адресом http://localhost/, как будто вы работаете с сервером в Интернете. Со здайте в этой папке папку ch9 — именно в ней мы будем сохранять работающие на стороне сервера сценарии.
Вне зависимости от того, с чем вы работаете — с XAMPP или с собственным вебсервером, задача будет одна: отправить на сервер информацию о погоде, как только игрок дойдет до контрольной точки. В качестве такой точки мы поместим в сцену зону триггера, напоминающую дверь из главы 8. Создайте куб, расположите его гденибудь в сторонке, укажите, что его коллайдер используется как триггер, и назначьте ему полупрозрачный материал, как и в предыдущем случае (напоминаю, что вам нужно настроить режим визуализации материала). Итоговый вид этого объекта показан на рис. 9.7.
Теперь, когда в сцене появился триггер, напишем код, который он будет активировать.
9.4. Отправка данных на веб-сервер 239
З а а: , а а
а а а
Рис. 9.7. Контрольная точка, вызывающая отправку данных на сервер
9.4.1. Слежение за погодой: отправка запросов POST
Код, активируемый в контрольной точке, будет последовательно включаться в нескольких сценариях. Как и в случае со скачиванием данных, при отправке данных сценарий WeatherManager заставляет сценарий NetworkService сделать запрос, причем последний полностью отвечает за передачу данных через сеть по протоколу HTTP. Следующий листинг демонстрирует коррективы, которые нужно внести в сценарий
NetworkService.
Листинг 9.17. Сценарий NetworkService с возможностью отправки данных
...
private const string localApi = "http://localhost/ch9/api.php"; ¬
...
private IEnumerator CallAPI(string url, Hashtable args, Action<string>
callback) { ¬ Аргументы, добавленные к параметрам метода CallAPI().
WWW www;
if (args == null) {
www = new WWW(url);
}else {
WWWForm form = new WWWForm(); ¬ Отправляем аргументы вместе с объектом WWW с помощью объекта WWWForm. foreach(DictionaryEntry arg in args) {
form.AddField(arg.Key.ToString(), arg.Value.ToString());
}
www = new WWW(url, form); ¬ Объект WWWForm автоматически меняет запрос с GET на POST.
}
yield return www;
...
}
public IEnumerator GetWeatherXML(Action<string> callback) {
return CallAPI(xmlApi, null, callback); ¬ Вызовы, измененные из-за измененных параметров.
}
public IEnumerator GetWeatherJSON(Action<string> callback) { return CallAPI(jsonApi, null, callback);
}
240 Глава 9. Подключение игры к Интернету
public IEnumerator LogWeather(string name, float cloudValue, Action<string> callback) {
Hashtable args = new Hashtable(); ¬ Определяем таблицу отправляемых аргументов. args.Add("message", name);
args.Add("cloud_value", cloudValue); args.Add("timestamp", DateTime.UtcNow.Ticks); ¬
return CallAPI(localApi, args, callback);
}
...
Прежде всего обратите внимание на новый параметр метода CallAPI(). Это таблица аргументов, отправляемая вместе с HTTP-запросом. В соответствии с этой таблицей в методе CallAPI() может быть создан объект WWWForm. Обычно объект WWW отправляет запросы GET, а объект WWWForm меняет их на запросы POST. Все остальные изменения в коде вызваны этим основным нововведением (например, модификация кода метода GetWhatever() из-за параметров метода CallAPI()).
Следующий листинг демонстрирует код, который нужно добавить в сценарий
WeatherManager.
Листинг 9.18. Добавление к сценарию WeatherManager кода отправки данных
...
public void LogWeather(string name) { StartCoroutine(_network.LogWeather(name, cloudValue, OnLogged));
}
private void OnLogged(string response) { Debug.Log(response);
}
...
И наконец, мы задействуем этот код, добавив к зоне триггера в сцене сценарий, управляющий контрольной точкой. Создайте сценарий CheckpointTrigger, свяжите его с зоной триггера и скопируйте в него код из следующего листинга.
Листинг 9.19. Сценарий CheckpointTrigger для зоны триггера
using UnityEngine;
using System.Collections;
public class CheckpointTrigger : MonoBehaviour { public string identifier;
private bool _triggered; ¬ Проверяем, срабатывала ли уже контрольная точка.
void OnTriggerEnter(Collider other) { if (_triggered) {return;}
Managers.Weather.LogWeather(identifier); ¬ Активируем отправку данных. _triggered = true;
}
}