close

Вход

Забыли?

вход по аккаунту

?

Polyshkina

код для вставкиСкачать
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
Федеральное государственное автономное
образовательное учреждение высшего образования
САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ
ОСНОВЫ РАБОТЫ В UNITY3D
Часть 2
Методические указания
по выполнению лабораторных работ
Санкт-Петербург
2015
Составители: А. В. Никитин, Н. Н. Решетникова, Е. А. Полушкина,
О. В. Косенко, А. А. Твердов
Рецензент – кандидат технических наук В. И. Исаков
Приведен цикл лабораторных работ по углубленному изучению
мультиплатформенной среды Unity3D для создания компьютерных
игр и интерактивных 2D/3D-приложений. Лабораторные работы направлены на освоение установки и управления характеристиками
камер в 3D-сцене, изучение способов ускорения рендеринга (визуализации) интерактивных 3D-сцен, а также создание простейшей многопользовательской 3D-игры с участием интеллектуального аватара
(бота).
Предназначены для студентов направления 09.04.01 (230100.68) –
«Информатика и вычислительная техника», изучающих дисциплины
магистерской программы «Системы мультимедиа и компьютерная
графика».
Публикуется в авторской редакции.
Компьютерная верстка М. И. Дударева
Подписано к печати 24.12.15. Формат 60 × 84 1/16.
Бумага офсетная. Усл. печ. л. 4,2. Тираж 100 экз. Заказ № 548.
Редакционно-издательский центр ГУАП
190000, Санкт-Петербург, Б. Морская ул., 67
© Санкт-Петербургский государственный
университет аэрокосмического
приборостроения, 2015
Введение
Unity3D является современной мультиплатформенной средой
(игровым движком – Game Engine) для создания компьютерных
игр и интерактивных 2D/3D приложений [1,2].
Графическая составляющая движка Unity3D не уступает его
основным конкурентам: Unreal Engine и CryEngine. Наиболее
отличительной особенностью движка Unity3D можно считать
огромное количество поддерживаемых платформ. Созданные с помощью Unity3D приложения работают под операционными системами Windows, OS X, Windows Phone, Android, Apple iOS, Linux,
а также на игровых приставках Wii, PlayStation 3, PlayStation
4, Xbox 360, Xbox One. Есть возможность создавать приложения
для запуска в браузерах с помощью специального подключаемого
модуля Unity (Unity Web Player), а также с помощью реализации
технологии WebGL. Помимо этого поддерживается физическая
технология NVIDIA PhysX, позволяющая проводить реалистичную симуляцию физики твердых и мягких тел. Написание логики осуществляется при помощи следующих языков программирования: C#, UnityScript (модифицированный Java Script) и Boo
(модифицированный Python). Редактор Unity3D, состоящий из
различных окон, имеет простой Drag&Drop интерфейс, который
легко настраивать, благодаря чему можно производить отладку
игры прямо в редакторе.
Проект в Unity3D делится на сцены (уровни) — отдельные файлы, содержащие игровые миры со своим набором объектов, сценариев, и настроек.
В редакторе имеется система наследования объектов; дочерние
объекты будут повторять все изменения позиции, поворота и масштаба родительского объекта, скрипты в редакторе прикрепляются к объектам в виде отдельных компонентов. Движок поддерживает множество популярных форматов для импорта трёхмерных
моделей, звуковых и видео файлов, изображений и текста. Кроме
того, редактор Unity3D имеет компонент для создания анимации,
3
но также анимацию можно создать предварительно в 3D редакторе
и импортировать вместе с 3D моделью объекта.
Установка дистрибутива, описание интерфейса Unity3D, основы создания 3D приложения, а также разработка простейшего интерфейса созданного приложения подробно рассмотрены в первой
части методических указаний по освоению Unity3D [3].
Настоящие методические указания (часть 2) для выполнения цикла лабораторных работ направлены на освоение установки и управления характеристиками камер в 3D сцене проекта Unity3D, изучение
способов ускорения рендеринга(визуализации) интерактивных 3D
сцен, а также создание простейшей многопользовательской 3D игры
(для Windows) с участием интеллектуального аватара (бота).
Концепция модели синтезированной камеры в современной
компьютерной графике алгоритмически опирается на синтез изображений, которые реально создаются в оптической системе. Однако, в компьютерной графике при отображении 3D объектов в окне
вывода одновременно задействованы несколько систем координат,
при котором происходит преобразование от локальных координат
(пространство объекта) в экранные (рис. 1).
Экранное пространство ограничивается свойственной ему пирамидой видимости, в зависимости от положения наблюдателя\
камеры. Во время визуализации следует учитывать, попадает ли
объект в пирамиду видимости или нет, что в свою очередь говорит
о необходимости использования алгоритмов отсечения невидимых
частей объекта (clipping) и алгоритмов удаления невидимых граней и ребер (culling). Основная функция системы Occlusion Сulling
игрового движка Unity3D, заключается в том, что у объектов, не
попадающих в поле зрения камеры, не визуализируется геометрия, что снижает нагрузку на центральный процессор и позволяет
оптимизировать проект.
Направление взгляда
наблюдателя
Yэ
Yл
Ym
Xл
Zл
Пространство
объекта
Xm
Zm
Мировое
пространство
Xэ
Экранное пространство
Рис. 1. Переход к экранному пространству
4
Еще одним методом ускорения процесса визуализации трехмерных сцен, которую поддерживает Unity3D, является создание уровней детализации (Level Of Detail, LOD). Его основная идея состоит
в том, что при рендеринге объектов, которые на данный момент
удалены от камеры, плохо видимы или имеют низкий приоритет,
используется менее детализованное представление, нежели, когда
эти же объекты оказываются близко к камере, хорошо видимы или
получают высокий приоритет.
При компиляции проекта Unity3D создается исполняемый
(.exe) файл 2D/3D приложения (для Windows) или игры, а в отдельной папке (Data) — данные игры, включая все игровые уровни и
динамически подключаемые библиотеки.
5
Лабораторная работа № 1
«ОЗНАКОМЛЕНИЕ С ФУНКЦИОНАЛЬНЫМИ
ВОЗМОЖНОСТЯМИ УПРАВЛЕНИЯ
ХАРАКТЕРИСТИКАМИ КАМЕРЫ»
Цель работы: ознакомится с функциональными возможностями управления характеристиками камеры, предоставленными
игровым движком Unity3D, а также исследовать возможности их
применения на тестовой модели.
Порядок выполнения:
1. Ознакомиться с содержанием раздела «Теоретические сведения»
2. Изучить функциональные возможности управления характеристиками камеры, предоставленные движком Unity3D.
3. Создать простейшую тестовую сцену в Unity3D.
4. Исследовать описанные свойства камеры на тестовой модели.
5. Сделать выводы.
6. Оформить отчет
Рекомендации по содержанию тестовой сцены:
– Стандартный Terrain
– Глобальное освещение (Directional light)
– First Person Controller
– Стандартные примитивы или простые модели.
– Более 2-х камер.
Пример тестовой сцены приведен на рисунке 1.15.
Теоретические сведения
Подобно тому, как камеры используются в фильмах для показа картины зрителям, камеры в Unity3D используются для показа
игрового мира игроку. Всегда существует, по меньшей мере, одна
камера, но можно добавить ещё несколько камер, которые позволят разделить экран для двух и более игроков или создать реалистичные визуальные эффекты. В Unity3D возможно создавать анимированные камеры или управлять ими по законам физики. С помощью камер можно получить практически любое изображение и
использовать стандартные и уникальные камеры, которые больше
подходят к стилю разрабатываемого приложения.
Рассмотрим более подробно устройство виртуальной камеры.
Внутреннее пространство усеченной пирамиды, которая изображена на рисунке – (рис.1.1) это та часть виртуального мира,
которую увидит пользователь с позиции установленной камеры.
Следует обратить внимание на три плоскости. Первая расположена
6
Задняя секущая
плоскость
Картинная
плоскость
Z
Передняя секущая
плоскость
Z=100
Z=1
Расстояние
до картинной
плоскости
Расстояние
до передней
секущей
плоскости
Расстояние до задней
секущей плоскости
Рис. 1. 1. Координатное пространство камеры
на расстоянии 1 по оси z. Это ближняя плоскость отсечения. То, что
находится до неё игрок никогда не увидит. В данном случае значение z равно единице, но оно может быть любым. Именно с ближней
плоскостью связан один из дефектов отображения графики, дефект
проявляется, прежде всего, в «шутерах» (shooter – стрелок) из-за
большой свободы движения камеры. Когда игрок слишком близко
подходит к объекту, то он может оказаться «внутри» объекта. Плоскость, расположенная на расстоянии 100 единиц по оси z называется дальней плоскостью отсечения. Расстояние может быть произвольным. Пользователь никогда не увидит объекты, расположенные
дальше этой плоскости. Шесть плоскостей, ограничивающих пространство, которое увидит пользователь, называются отсекающими
(clipping planes): левая, правая, верхняя, нижняя, ближняя и дальняя. Плоскость, расположенная между ближней и дальней плоскостями называется проекционной или картинной плоскостью. Проекционная плоскость предназначена для последнего преобразования координат: преобразование из трёхмерного пространства
камеры – в двухмерное изображение, именно благодаря проекционной плоскости пользователь увидит виртуальный мир. Собственно,
проекция части трехмерного пространства, видимого в объектив камеры, на картинную плоскость и есть то, что увидит пользователь.
7
Поле зрения/зона обзора (field-of-view)
Ширина и высота проекционной/катинной плоскости определяется положением центра проецирования и его расстоянием до картинной плоскости, поле зрения или зона обзора (рис.1 .2). Обозначается как«fields of view».
Буфер глубины (z-buffer / depth-buffer)
Буфер глубины – двумерный массив данных, дополняющий двумерное изображение, где каждому пикселу (фрагменту) изображения сопоставляется «глубина» (расстояние от наблюдателя до поверхности изображаемого фрагмента объекта).
Как известно, в 3D моделировании используется принцип
“overdraw”, то есть сначала прорисовываются объекты, которые
находятся дальше от камеры, а затем поверх этих объектов – объекты, выходящие на передний план (рис. 1.3).
В компьютерной графике используется специальный механизм,
который имеет название: z-буфер или буфер глубины. Размер
z-буфера по количеству элементов совпадает с размером буфера кадра [4]. В результате сравнения в z-буфер заносится z-координаты
самого ближнего к камере объекта. В примере, приведенном на
рис.1.3б, оранжевый треугольник частично перекрывает красный,
и, соответственно, в буфер глубины будут занесены z-координаты
оранжевого треугольника.
Виды проецирования
Проецирование – это отображение трехмерного объекта на плоскость при помощи прямых проецирующих лучей, проходящих через характерные точки объекта, например через его вершины [4].
Если все проецирующие прямые выходят из одной точки, то
проецирование называется центральным или перспективным, а
точка, из которой выходят лучи, называется центром проецирования (рис. 1.4).
Наибольший угол между проецирующими лучами называется углом зрения (рис. 1.2). Чтобы получить наиболее выразительную перспективную проекцию, угол зрения следует выбирать в диапазоне от 20° до 40°.
Если же центр проецирования находится на бесконечно большом
расстоянии от плоскости проекций, проецирующие лучи параллельны друг другу, то проекция 3D объекта называется параллельной.
Если проецирующие лучи при параллельном проецировании
перпендикулярны плоскости проекций, то проецирование называется ортографическим.
8
Y
а)
б)
Z
FOVX
FOVY
Z
X
Рис. 1. 2. Зоны обзора задаются двумя углами
а) –fovx – зона обзора по горизонтали; б) – fovy – зона обзора по вертикали
а)
б)
Z
Z
Z
= 50
= 25
X
Рис. 1. 3. Перекрываемые объекты на картинной плоскости
а) –вид сверху на два треугольника, расположенных на расстоянии в 25
и 50 единиц от камеры. б) –конечное изображение
Y
ПЛОСКОСТЬ
ПРОЕКЦИИ
Z
ЦЕНТР ПРОЕЦИРОВАНИЯ
0
X
Рис. 1.4. Центральное (Перспективное) проецирование
9
Ортографическое (прямоугольное) проецирование
В черчении при создании чертежей объектов используются их
ортографические (прямоугольные) проекции (ОП) на три плоскости: фронтальную, горизонтальную и профильную (рис. 1.5).
Виртуальная камера в Unity3D
Камеры используются для отображения игроку игрового мира.
Поэтому в каждой сцене присутствует минимум одна камера, их
количество не ограничено. Несколько камер может использоваться для разделения экрана для двух игроков, создания спецэффектов. Манипулируя камерами, можно придать игре/приложению
уникальный вид, значительно повысить реалистичность проектов. Изображения с камеры могут визуализироваться в любой последовательности в любом месте экрана или только в указанных
частях экрана. Таким образом, камера является достаточно гибким объектом.
На рисунке 1.6 показано окно проекта Unity3D с заданным объектом Main Camera и его характеристиками в окне Inspector.
Y
ФРОНТАЛЬНАЯ
ПРОФИЛЬНАЯ
ПЛОСКОСТЬ ПРОЕКЦИИ
ПЛОСКОСТЬ ПРОЕКЦИИ
Z
X
ГОРИЗОНТАЛЬНАЯ
ПЛОСКОСТЬ ПРОЕКЦИИ
Рис. 1.5. Ортографическое (прямоугольное) проецирование
10
Рис. 1.6. Объект Main Camera в Unity 3D
Мультиплатформенная среда Unity3D предоставляет разработчику богатые возможности управления характеристиками камеры
[2]. Рассмотрим некоторые свойства камеры (рис. 1.7) .
Рис. 1.7. Свойства объекта MainCamera в окне Inspector
11
Таблица 1.1
Свойства камеры в пакете Unity 3D
ClearFlags
Background
CullingMask
Определяет, какие части экрана будут стёрты
(не будут отрисовываться) . Это полезно, когда
применяется несколько камер для отрисовки
разных элементов игры.
Цвет, используемый для части экрана, не занятой объектами, в случае, если нет SkyBox (небо)
Включает или исключает слои объектов отображаемые камерой. Назначение слоев объектам
происходит в окне Inspector.
Projection
Переключение камеры для возможности отображения вида в перспективе.
Perspective
Камера будет отображать объекты в режиме
перспективного просмотра.
Камера будет отображать объекты в ортогональном режиме (без эффекта глубины).
Size (Если выбран орто- Размер окна просмотра камеры при установке
гональный вид)
ортогонального вида.
Orthographic
Fieldofview
ClippingPlanes
Near
Far
Ширина угла обзора камеры, измеряется в градусах относительно локальной оси Y.
Расстояние от камеры до начала и конца отображения.
Ближайшая к камере точка, для которой будет
строиться изображение.
Самая дальняя от камеры точка, для которой
строится изображение.
NormalizedViewPortRect
Четыре значения, определяющие область
отображения камеры в координатах экрана
(значения от 0 до 1).
X
Начальное положение по горизонтали, в котором отображается камера.
Y
Начальное положение по вертикали, в котором
отображается камера.
W (Width)
Ширина области отображения камеры на экране.
H (Height)
Высота области отображения камеры на экране.
Depth
Положения камер в порядке отображения. Области отображения камер с большими значениями отображаются над областями камер с меньшим значением.
12
Таблица 1.1
RenderingPath
Настройка, определяющая метод отображения
используемый камерой.
UsePlayerSettings
Камера будет использовать путь отображения
в зависимости от того какие настройки выставлены в thePlayerSettings.
VertexLit
Все объекты, отображаемые камерой, будут
отображаться как Vertex-Lit- объекты.
Forward
Все объекты отображаются за один проход
для каждого материала (является стандартом
в Unity 2.x).
Все объекты будут отрисованы сразу без освещеDeferred Lighting (толь- ния, Освещение для всех объектов будет отобрако в PRO-версии)
жено в последнюю очередь.
Ссылка на RenderTexture, которая будет соTarget Texture (Тольков держать изображение с камеры. Создание этой
ссылки делает невозможным вывод изображеUnity Pro/Advanced)
ния с камеры на экран.
HDR
Включает HighDynamicRange рендеринг для
камеры.
CLEAR FLAGS (Очищение флагов)
Каждая камера хранит информацию о цвете и глубине каждого
из видимых объектов 3D сцены, когда она визуализирует видимую
часть пространства. Участки экрана, на которые не происходит
отрисовка объектов – пусты, и по умолчанию будут отображать
Skybox. Когда используется несколько камер, каждая из них сохраняет свою собственную информацию о глубинах и цвете в буферах,
собирая как можно больше данных для визуализации(рендеринга).
Так как каждая из камер на сцене визуализирует лишь ту часть,
которая видима с ее собственной позиции, следует установить значения ClearFlags, чтобы очищать различные наборы информации
из буферов (рис.1.8).
– Skybox
Этот вариант включён по умолчанию. Все пустые участки экрана будут отображать Skybox текущей камеры. Если у текущей камеры нет Skybox, будет использоваться стандартный Skybox, указанный в RenderSettings (Edit→RenderSettings). Если и его нет, то
используется фоновый цвет (BackgroundColor).
13
Рис.1.8. Свойство камеры ClearFlags
– SolidColor.
Все пустые участки экрана будут закрашены фоновым цветом
(BackgroundColor).
– DepthOnly.
Особенно удобно использовать, когда требуется отрисовать оружие
игрока. Для этого создается две камеры, одна (глубина 1) для отрисовки оружия, вторая(глубина 0) для окружающей среды. У камеры для
оружия ClearFlags должен быть установлен в “depthonly”.
– Don’tClear.
Этот режим не очищает ни буфер цвета, ни буфер глубины. В результате каждый кадр отрисовывается поверх следующего, образуя эффект
смазывания. Обычно не используется в играх, и подходит для использования вместе с пользовательским шейдером.
CLIP PLANES (Плоскости отсечения)
NearClipPlane и FarClipPlane определяют, на каком расстоянии
объекты начинают отрисовываться камерой и на каком – заканчиваются. Эти границы отсекаются плоскостями, которые расположены перпендикулярно направлению луча из камеры и позиция их
определяется расстоянием до камеры. NearPlane определяет ближнюю границу, а FarPlane – дальнюю(рис. 1.9).
Объекты начинают отрисовываться камерой на расстоянии 0,3 и
заканчиваются на расстоянии 5.
Рис. 1. 9. ClipPlane
14
NORMALIZED VIEW PORT RECTANGLE
(Позиционирование камеры)
Normalized Viewport Rectangles определяет местоположение
изображения с камеры на экране и отведённую для него площадь.
Например, для того, чтобы создать два разделенных экрана в настройках каждой камеры следует установить значение
H=0.5 и для первой камеры(Camera 1) присвоить Y=0.5(см. рис.
1.10 и 1.11).
Результат применения Normalized Viewport Rectangles приведен на рисунке 1.12.
Рис. 1.10. Camera 1
Рис. 1.11. Camera 2
Рис. 1.12. Результат применения Normalized Viewport Rectangles
15
DEPTH(Глубина)
Как уже говорилось выше, Unity3D позволяет создавать неограниченное количество камер. Для каждой камеры назначается различная глубина видимого пространства (Depth). Таким образом,
они будут отрисовываться в порядке от меньшей глубины к большей. Другими словами камера с глубиной 2 будет отрисована поверх камеры с глубиной 1.
PROJECTION (Проекция)
Перспективная и Ортографическая(Параллельная) проекции. – ORTHOGRAPHIC
Включение ортографического режима удалит все перспективные искажения. Обычно это используется при создании изометрических или двухмерных игр.
CULLINGMASK (Маска отбора)
Сullingmask (рис.1.14) используется для выборочной визуализации (рендеринга) групп объектов с использованием слоев
(Layers).
В общем случае, хорошей практикой является расположение
интерфейса пользователя на отдельном слое, чтобы затем интерфейс визуализировался отдельной камерой, предназначенной для
отрисовки слоя интерфейса пользователя.
Для того, чтобы интерфейс отображался поверх изображений
с других камер, потребуется установить ClearFlags в “Depthonly” и
убедиться, что глубина для камеры пользовательского интерфейса
выше, чем у остальных камер.
HDR(High Dynamic Range)
High Dynamic Range Rendering, часто сокращается до High
Dynamic Range — графический эффект, применяемый в играх для
наиболее выразительного рендеринга изображения при контрастном освещении сцены.
Пример тестовой сцены приведен на рис. 1.15.
Рис. 1.13. Свойство виртуальной камеры Projection
16
Рис. 1.14. Свойство виртуальной камеры – CullingMask
Рисунок 1.15. Пример тестовой сцены
Содержание отчета
1. Титульный лист, оформленный в соответствии с ГОСТ.
2. Цель работы и задание на выполнение работы.
3. Описание объектов сцены.
4. Описание процедуры установки и настройки характеристик
камеры.
5. Привести общий скриншот 3D-сцены.
6. Скриншоты 3D-сцены, видимые с различных позиций камеры.
7. Анализ результатов и выводы.
17
Контрольные вопросы
1) Что такое плоскость отсечения? Картинная плоскость?
2) Сколько плоскостей отсечения используется для определения
видимого пространства 3D сцены?
3) Назначение проекционной\картинной плоскости?
4) Как регулируется область видимого пространства камеры?
5) Сколько камер может быть установлено в 3D сцене?
6) Какие реалистичные визуальные эффекты можно привязать
к камере?
7) Как настроить несколько камер так, что бы была возможность
использовать любую из них, как основную (главную) камеру (main
camera)?
8) Назовите способы анимации камеры в Unity3D?
9) Возможно ли управление камерой с применением физических
законов?
10) Когда применяется включение ортографического режима
камеры?
18
Лабораторная работа № 2
«ОЗНАКОМЛЕНИЕ С ФУНКЦИОНАЛЬНЫМИ
ВОЗМОЖНОСТЯМИ УПРАВЛЕНИЯ
ПИРАМИДОЙ ВИДИМОСТИ»
Цель работы: ознакомиться с функциональными возможностями управления пирамидой видимости, предоставленными движком Unity3D, исследовать возможности функции Occlusion Culling
на тестовой модели, сделать выводы.
Порядок выполнения:
1. Ознакомиться с содержанием раздела «Теоретические сведения».
2. Изучить функциональные возможности управления пирамидой видимости, предоставленные Unity3D.
3. В Unity3D создать тестовую сцену.
4. Исследовать возможности функции Occlusion Culling на тестовой сцене.
5. Предоставить результаты проверки сгенерированной окклюзии:
а) Окно статистики (до и после применения Occlusion Culling).
б) Скриншоты экрана в режиме Visualize (до и после применения Occlusion Culling).
6. Сделать выводы о проделанной работе
7. Оформить отчет.
Рекомендации по содержанию тестовой сцены:
Тестовая сцена должна содержать:
– Стандартный Terrain
– Глобальное освещение (Directionallight)
– First Person Controller
– Стандартные примитивы:
– куб (n*n*n) ~ 20 шт.
– куб (5n*n*n) ~ 20 шт.
– куб (n*5n*n) ~ 20 шт.
– куб (n*n*5n) ~ 20 шт.
– куб (n*n*n) ~ 10 шт.
Стандартные примитивы должны быть расставлены в случайном порядке.
Теоретические сведения
Основная проблема интерактивных 3D-приложений обусловлена тем, что как правило требуется моделирование большого количества высокополигональных объектов, которое ухудшает взаи19
модействие пользователя с приложением в реальном времени. Для
решения этой проблемы требуется использование современных механизмов управления количеством объектов сцены, попадающих
в пирамиду видимости.
Occlusion Culling (Удаление скрытых частей)[2] – это функция,
которая отключает рендеринг объектов, закрытых другими объектами. Сразу стоит отметить, что эта функция доступна только
в Pro-версии движка Unity3D. Поскольку при 3D моделировании
используется принцип “overdraw”(сначала прорисовываются объекты, которые находятся дальше от камеры, а затем поверх этих
объектов – объекты, выходящие на передний план), то, к сожалению, это не происходит автоматически. Следует обратить внимание, что функция Occlusion Culling отличается от Frustum Culling
(отсечение по пирамиде видимости). Frustum Culling отключает
рендеринг только тех объектов, которые не попадают в пирамиду
видимости, но не рендер объектов, спрятавшихся один за другим.
Однако, при использовании Occlusion Culling важно использование
и функции Frustum Culling. Действие функций представлено соответственно на рис. 2.1а и 2.1б, из которых наглядно видно, что
Occlusion Culling охватывает и отключает рендер большего количества “невидимых” объектов, а следовательно благотворнее влияет
на показатель Fps(количество кадров в секунду), т. е. производительность приложения.
Рис. 2.1а. Рендеринг сцены без применения функции OcclusionCulling
20
Рис. 2.1б. Рендеринг сцены с использованием функции OcclusionCulling
Процесс Occlusion Culling
Процесс реализации функции Occlusion Culling осуществляется
следующим образом. Виртуальная камера, проходя сцену, создает иерархию потенциально видимых множеств объектов. При запуске приложения камера использует эту информацию, определяя, какие объекты видны, а какие нет в данный момент времени. Таким образом происходит рендер только видимых объектов. Все данные Occlusion Culling
представляются набором клеток, каждая из них – это некоторый объем
сцены. Таким образом, клетки образуют бинарное дерево.
Occlusion Culling одно дерево для двух видов, а именно:
– ViewCells (окно для статических объектов)
– TargetCells (окно для динамических объектов)
ViewCells сопоставляется со списком индексов, определяющих
видимость статических объектов. Это дает более точный результат
для определения статичных объектов.
Очень важно помнить эту информацию при создании своего
приложения, потому что крайне важно создать хороший баланс
между размерами объектов и размерами клеток. В идеальном варианте не должно быть клеток, слишком малых по сравнению с объектами, но и не должно быть объектов, которые занимают много
клеток. Можно разбить крупные объекты на более мелкие части,
можно объединить мелкие объекты, что уменьшит drawcalls. Совокупность клеток и информация об их видимости называется PVS
(PotentiallyVisibleSet – потенциально видимый набор).
Настройка Occlusion Culling
Для использования Occlusion Culling необходимо выполнить ряд
настроек. Первый этап – разбиение всей геометрии сцены на части
21
разумного размера. Также важно разбить уровни на небольшие,
четко определенные области, которые закрыты другими крупными объектами(здания, стены и т.п.) Видимость каждой области будет включаться и выключаться в зависимости от данных Occlusion
Culling. Например, если выделить каждый объект интерьера отдельной областью, то они будут видимы или невидимы в зависимости от
поворота камеры. Либо если есть объект, который содержит все элементы интерьера, тогда весь набор будет либо виден, либо невиден.
Во-первых, в Inspector следует обозначить объекты, которые
нужно включить в Occlusion Culling как OccluderStatic. Наиболее
быстрый путь – мультивыделение объектов, каждый раз помечая
их как OcclusionStatic или OccludeeStatic. OccludeeStatic используется для прозрачных или очень маленьких объектов, которые ничего не закрывают сами, но будут закрываться другими объектами.
Это помогает уменьшить вычисления.
Рис. 2.2 Обозначение объекта для Occlusion Culling
22
Рис. 2.3. Окно Occlusion Culling
Для основных настроек Occlusion Culling удобнее использовать
окно Occlusion Culling (Window ->Occlusion Culling)
В данном окне можно работать либо с Occlusion Mesh, либо
Occlusion Area.
Occlusion Area
Во-первых, если не задать OcclusionAreas, то по умолчанию
Occlusion Culling будет применен ко всей сцене целиком.
Во-вторых, когда камера находится вне Occlusion Area, то
Occlusion Culling не будет работать. Необходимо установить Occlusion
Areas, чтобы определить места, где может находиться камера.
В-третьих, слишком большие области OcclusionArea усложняют
процесс Backing.
Для того, чтобы применить OcclusionСulling к динамическим
объектам, создаются OcclusionArea. Размер меняется таким образом, чтобы в области поместились все необходимые объекты. Для
того, чтобы создать OcclusionArea, нужно добавить компонент
OcclusionArea пустому GameObject.
GameObject (Component > Rendering > Occlusion Area из пункта
меню) (рис. 2.4). На рис. 2.5 приведено окно настроек оптимизированной области Occlusion Area.
23
Рис. 2.4. Создание Occlusion Area
Рис. 2.5. Окно настроек оптимизированной
области Occlusion Area.
В табл. 2.1 приведено описание настоек области Occlusion Area,
а в табл. 2.2 – настройки параметров Target Resolution.
24
Таблица 2.1
Настройки Occlusion Area
Size
Center
IsViewVolume
IsTargetVolume
Определяет размер оптимизируемой области
Определяет координаты центра Occlusion Area. По
умолчанию – это координаты (0,0,0)
Определяет, где может располагаться камера. Требуется для скрытия статических объектов, находящихся в зоне Occlusion Area.
Требуется для скрытия динамических объектов.
Определяет точность окклюзии. Влияет на размер клеток Occlusion Area. Влияет только на
TargetResolution
области,в которых находятся динамические объекты
(TargetAreas).
Таблица 2.2
Настройки TargetResolution
Low
Рассчитывает данные быстро, но не очень точно.
Medium
Баланс между временем расчёта данных окклюзии и
точностью расчетов.
High
Рассчитывает данные медленнее, но точность выше.
VeryHigh
Очень высокая точность (для приложений с большим
разрешением). Значительно увеличивается время расчетов.
ExtremelyHigh
Самый точный расчет данных окклюзии для динамических объектов. Очень долгое время расчета.
После того, как была создана Occlusion Area, необходимо проверить, каким образом произошло разбиение бокса на клетки. Для
этого нужно выбрать Edit и в панели Occlusion Culling Preview
Panel нажать кнопку View.
Рис.2.6. Occlusion Culling Preview Panel
25
Occlusion Culling – Bake
При настройке Baking (запекание) следует обратить внимание
на вкладку Technique, которая отвечает за тип Baking (рис. 2.7).
Рис. 2.7. Окно настроек Bake
Таблица 2.3
Типы Baking
26
PVS only
Только статические объекты подвергаются процессу
Occlusion Culling. Динамические объекты отсекаются по
принципу Frustum Culling. Этот метод меньше всего загружает процессор. Но поскольку динамические объекты
не отсекаются по принципу Occlusion Culling, то такой
способ рекомендуется для приложений с небольшим количеством динамических объектов и персонажей.
Так как видимость объектов вычисляется заранее, во время выполнения приложения невозможно открывать или
закрывать порталы.
PVS and
dynamic
objects
Отсечение статических объектов происходит заранее. Динамические объекты отсекаются по принципу Portal Culling
(портальное отсечение). Этот метод является хорошим
балансом между затратами на выполнение приложения и
эффективностью Occlusion Culling. Поскольку видимость
объектов вычисляется заранее, во время выполнения приложения невозможно открывать или закрывать порталы.
Продолжение таблицы 2.3
Automatic
Portal
Generation
Автоматическая генерация порталов. Статические и
динамические объекты отсекаются через порталы. Этот
метод позволяет открывать и закрывать порталы во время
выполнения приложения. В данном случае отсечение объектов будет происходить более точно, но и процессор будет
работать с большей нагрузкой.
Таблица 2.4
Настройки Backing
ViewCellSize
Размер каждой клетки области. Меньший размер клетки обеспечивает более точный Occlusion Culling. Размер
обеспечивает оптимальное соотношение между точностью отсечения и заданным размером.
NearClipPlane
Ближайшая плоскость отсечения. Необходимо установить минимальное значение ближайшей плоскости
отсечения для всех камер.
FarClipPlane
Максимальная плоскость отсечения. Используется для
отсечения объектов. Все объекты, находящиеся дальше этого расстояния будут автоматически отсекаться.
(Необходимо установить максимальное значение дальней плоскости отсечения для всех камер).
Memorylimit
Указывает объем выделенной памяти для Backing,
основанного на PVS. Недоступно в режиме Automatic
Portal Generation.
После того, как будут завершены все настройки, чтобы начать процесс Occlusion Culling следует нажать кнопку Bake. Уточните Memory
Limit (лимит памяти) во вкладке Bake. Меньшее значение этого параметра позволит сгенерировать данные гораздо быстрее, но с меньшей точностью. Большее значение используется для создания высококачественных приложений. После завершения процесса, в области
ViewArea появятся цветные кубики. Закрашенные области – это
области, содержащие соответствующие данные окклюзии.
Чтобы удалить все предшествующие расчеты – нажмите кнопку Clear.
Проверка результатов окклюзии
Для того, чтобы проверить сгенерированную окклюзию выберите Occlusion Culling (в панели Occlusion Culling Preview Panel выберите режим Visualize) и перемещайте камеру (MainCamera) в режиме SceneView.
27
Рис. 2.8. Скриншот сцены до применения Occlusion Culling
Рис. 2.9. Скриншот сцены после применения функции Frustum Culling
Рис. 2.10. Скриншот сцены после применения функции Occlusion Culling
28
Рис. 2.11. Окно статистики после
применения функции Occlusion Culling
Рис.2.12. Пример расположения стандартных примитивов
Еще одним инструментов для проверки сгенерированной окклюзии служит окно статистики в режиме Game.
29
Содержание отчета
1) Титульный лист, оформленный в соответствии с ГОСТ.
2) Цель работы и задание на выполнение работы.
3) Описание порядка действий для настройки функции Occlusion
Culling.
4) Описание порядка действий для проверки сгенерированной
окклюзии.
5) Привести результаты(скриншоты экрана) проверки сгенерированной окклюзии.
6) Выводы о проделанной работе
Контрольные вопросы
1) Для чего требуется применение механизмов управления количеством объектов сценой, попадающих в пирамиду видимости?
2) Что относится к основным моментам настройки функции
Occlusion Culling?
3) Когда следует использовать Occludee Static?
4) Что такое Occlusion Area?
5) Какие показатели определяют качество сгенерированной окклюзии?
30
Лабораторная работа № 3
«ИЗУЧЕНИЕ МЕХАНИЗМА УРОВНЕЙ ДЕТАЛИЗАЦИИ»
Цель работы: изучить применение уровней детализации (LOD)
объектов в интерактивной трехмерной сцене, реализовать на практике статический/дискретный LOD в среде Unity3D и проанализировать влияние LOD на параметры рендеринга.
Порядок выполнения:
1. Ознакомиться с содержанием раздела «Теоретические сведения».
2. Изучить способы подключения уровней детализации (LOD)
объектов в Unity3D.
3. Создать простейшую тестовую сцену в Unity3D.
4. Подготовить заданное преподавателем количество 3D моделей объектов с различным уровнем детализации в формате .fbx, используя 3D редактор.
5. Импортировать подготовленные 3D модели в Unity3D и на их
основе создать дискретный LOD.
6. Проанализировать данные статистики для созданной 3D сцены и сделать выводы.
7. Оформить отчет.
Рекомендации по содержанию тестовой сцены:
Тестовая сцена должна содержать:
– Стандартный Terrain
– First Person Controller
– Directional Light
Количество уровней детализации объектов (LOD) от 2 до 4.
Число полигонов для модели нулевого уровня (LOD 0) не должно
быть менее (m+n+s)*100.
Теоретические сведения
Одним из методов ускорения процесса визуализации трехмерных сцен является механизм уровней детализации (Level Of Detail
или LOD). Его основная идея состоит в том, что при рендеринге объектов, которые на данный момент удалены от камеры и плохо видимы, следует использовать их менее детализованное представление,
нежели, когда эти же объекты оказываются близко к камере, хорошо видимы и получают высокий приоритет.
Для работы механизма необходимо наличие нескольких представлений 3D-объектов с различной степенью визуального разрешения или различными уровнями детализации. Уровнем детали31
зации называется некоторая аппроксимация начальной модели
объекта с использованием меньшего количества геометрических
элементов – полигонов [5].
В целом, любой алгоритм LOD состоит из трех основных частей,
а именно: генерации, выбора и переключения. Генерация LOD – это
та часть, где различные представления модели генерируются с разными уровнями детализации. Алгоритм выбора определяет, какой
из уровней детализации модели использовать в данный момент
в зависимости от определенной метрики, такой как, например, занимаемая моделью площадь на экране, или расстояния от нее до
камеры. Наконец, третья часть, алгоритм переключения, описывает, как именно должен происходить переход от одного уровня детализации к другому.
С точки зрения генерации алгоритмы LOD можно разделить на
статические и динамические:
– Статические – в которых, все данные подготавливаются однократно при построении модели, а в ходе визуализации(рендеринга)
происходит только переключение между заранее подготовленным
уровнями детализации.
– Динамические – в которых, уровень детализации модели пересчитывается непосредственно в процессе визуализации(рендеринга)
в зависимости от текущих метрик объекта (расстояния до наблюдателя, скорости и т. д.).
Статические LOD-алгоритмы легко программируются и позволяют использовать аппаратное ускорение. Есть возможность упаковать
их в дисплейные списки, вершинные массивы и т.д., что позволяет
значительно ускорить визуализацию, так как такие структуры отрисовываются на экране современной аппаратуры в 3–5 раз быстрее,
чем неструктурированные полигоны. Создание и визуализация разделены, а значит, уровни детализации будут создаваться однократно
в момент подготовки 3D модели и не подвержены ограничениям интерактивной визуализации, от самой визуализации требуется только выбрать нужный уровень представления 3D объекта.
К недостаткам статических LOD-алгоритмов можно отнести невозможность применения их для радикального упрощения геометрии при ландшафтном моделировании, моделировании трехмерных изоповерхностей, сложных CAD-моделей и данных с трехмерных дистанционных сканеров.
Динамические LOD-алгоритмы напротив, создаются непосредственно в процессе рендеринга, что требует затрат вычислительных
мощностей. Однако в этом случае уровень детализации модели всег32
да будет точно соответствовать текущему значению метрики, и, следовательно, будет использовать не больше полигонов, чем необходимо
в данный момент. Помимо этого, динамические LOD-алгоритмы, проигрывая статическим по затратам процессорного времени, выигрывают у них по памяти, поскольку нет необходимости хранить заранее
заготовленные 3D объекты различных уровней детализации.
В книге Д. Любке приведена следующая классификация LODалгоритмов [5]:
– Дискретный LOD – для объектов заранее подготавливаются
варианты моделей разных степеней детализации. Переход между
моделями осуществляется резко при переходе метрики через определенный уровень. При этом возникает т.н. эффект «перепрыгивания» (popping), выражающийся в том, что резкое изменение модели визуально заметно для наблюдателя. Для его сглаживания на
этапе «переключения» используются дополнительные приемы,
рассматриваемые ниже.
– Непрерывный LOD – при построении модели для объектов
подготавливаются специальные структуры данных, кодирующие
непрерывный спектр уровней детализации. Далее при рендеринге
уровень детализации определяется, как функция одной или нескольких метрик объекта (например, расстояние до объекта и т.п.).
– Видозависимый LOD – расширяет идею непрерывного LOD,
позволяя задавать разные степени детализации для разных частей
одного и того же объекта. Таким образом, для сложных объектов,
их более удаленная от наблюдателя часть будет менее детализированной, нежели близкая к нему. В отличии от непрерывного LOD
уровни не кодируются заранее, а генерируются динамически для
тех объектов, которые попадают в пирамиду видимости.
Дискретный LOD и борьба с эффектом «перепрыгивания»
В случае дискретного LOD непрерывный диапазон значений некоторой метрики разбивается на интервалы, каждому из которых
сопоставляется один из предопределенных уровней детализации.
Пример для случая, когда метрикой является расстояние до наблюдателя приведен на рис 3.1. Наблюдатель находится в центре,
уровни детализации образуют концентрированные вокруг него
окружности. Темные области соответствуют более высоким уровням детализации. Рисунок также демонстрирует, что последнему
интервалу, ограниченному сверху бесконечностью, соответствует
исчезновение объекта. Также применяется клиппинг (clipping – отсечение видимого объема по окну вывода). Отметим, что исчезнове33
Рис. 3.1. Пример различных диапазонов дискретного LODа.
ние объекта в последнем интервале совпадает в данном случае с отсечением по дальней плоскости пирамиды видимости (см. рис. 1.1).
Однако если бы метрикой была, к примеру, экранная площадь, то
это были бы два различных процесса.
В качестве метрики для такого подхода могут быть выбраны расстояние между объектом и камерой или площадь занимаемая объектом на экране (более точная метрика, нежели расстояние, но и
более вычислительно затратная). Помимо значения метрик в процессе рендеринга могут учитываться приоритеты объектов, некоторые из которых должны всегда быть более детализованы, чем
остальные.
Важным моментом при использовании дискретных LOD является наличие гистерезиса при выборе уровня детализации. Переключение происходит на разных значениях метрики в зависимости от
того, в какую сторону оно выполняется. Так, например, объект может терять детализацию на значение метрики в 105, а приобретать
ее на значение в 95. Гистерезис гарантирует, что объект не будет
дергаться между двумя уровнями детализации, если метрика будет
колебаться вблизи границы переключения.
Дискретные LOD – это самый распространенный тип LOD [5],
наиболее простой в реализации и замечательно сочетающийся
с преимуществами статических LOD. Кроме того, поскольку уровни детализации в случае дискретного LOD выбираются/корректируются создателем модели, то дискретные LOD застрахованы от
возникновения некачественных и некорректных уровней детали34
зации. С другой стороны, дискретные LOD характеризуются потерями производительности из-за избыточной детализации объектов: уровень детализации будет соответствовать выбранной метрике только непосредственно в моменты переключения с одного уровня на другой. Помимо этого, большие 3D объекты, особенно модели
земной поверхности, слишком велики и какая-то их часть всегда
будет слишком близко к камере, чтобы дискретный подход мог работать с ними. Наконец, эффект «перепрыгивания» проявляет себя
в случае с дискретными LOD-алгоритмами наиболее ярко.
Под эффектом «перепрыгивания» (popping) понимается ситуация, когда изменение модели объекта (в данном случае при переходе между уровнями детализации) происходит чересчур резко и оказывается заметно и очевидно для наблюдателя. «Перепрыгивание»
наиболее ярко проявляется при переключении между различными
уровнями детализации напрямую без промежуточных шагов. Для
снижения данного эффекта в алгоритмах LOD используются такие
методы, как геоморфинг (geomorph) и смешение уровней детализации (LOD blending), дающие плавный переход.
Смешение уровней детализации, также известное, как альфа-смешение, снижает эффект «перепрыгивания» путем отображения обоих
уровней детализации модели одновременно, смешивая их вместе в течение небольшого времени переключения между уровнями.
Смешение уровней детализации имеет значительный недостаток. Оно затратно с точки зрения вычислительных мощностей, поскольку в процессе смешения оба уровня детализации
визуализируются(рендерятся) одновременно, что может негативно повлиять на производительность, поскольку задача алгоритмов
LOD снизить сложность объектов на сцене, а не увеличить ее вдвое,
как это происходит во время смешения.
В отличие от альфа-смешения, геоморфинг уменьшает эффект
перепрыгивания в процессе смены уровней детализации путем
добавления аппроксимаций трехмерной модели, которые служат
в качестве промежуточных шагов между двумя уровнями детализации, создавая эффект плавного перехода[5]. Основные операции,
использующиеся для этих промежуточных аппроксимаций – это
свертывание ребер (удаление вершин) и разбиение вершин (добавление вершин). По сути своей геоморфинг является своего рода
промежуточным вариантом между дискретными и непрерывными
алгоритмами LOD, описанными ниже. На рисунке 3.2 приведены
графики зависимости уровня детализации от выбранной метрики
для дискретных LOD с использованием геоморфинга и без него.
35
Y
Y
X
X
а)
б)
Рис 3.2. Графики зависимости уровня детализации от выбранной
метрики для а) Чистого дискретного LOD, б) Дискретного LOD
с использованием геоморфинга
Таким образом, при использовании дискретных LOD в интерактивных сценах в настоящее время лучшей рекомендацией будет использование альфа-смешения для борьбы с эффектом «перепрыгивания». Применение же геоморфинга, несмотря на потенциально
лучшие результаты в первую очередь должно начинаться с анализа
возможности использования для объекта одного из непрерывных
вариантов LOD.
Непрерывный LOD
Основная идея непрерывного LOD основывается на алгоритме
прогрессирующих полигональных поверхностей Хоппа (Hugues
Hoppe: Hoppe’s progressive mesh algorithm) [6]. Этот алгоритм дает на выходе не отдельные, дискретные уровни детализации, но
непрерывный их спектр, хранимый в виде базовой примитивной
модели и серии уточняющих операций. Степень детализации текущей модели зависит от числа примененных к ней уточняющих
операций. Конкретный алгоритм, применяемый для получения
спектра может отличаться от алгоритма Хоппа, но основная идея
остается неизменной.
В число уточняющих операций входят, в частности, алгоритмы
свертывания ребер и разделения вершин, представленные на рис.
3.3. Поскольку эти операции взаимнообратны, то ими соответственно описываются два пути движения по спектру: при уменьшении
детализации каждая последующая сетка отличается от предыдущей
на одну операцию свертывания ребра, а при увеличении детализации – на одну операцию разделения вершины.
Для операции свертки ребра различают два основных варианта,
представленных на рис. 3.4 – полную свертку и полусвертку.
36
V4
V5
V5
V3
VБ
V6
V4
РАЗДЕЛЕНИЕ
V3
V6
VА
V2
V7
V1
VP
V2
СВЕРТЫВАНИЕ
V7
V1
Рис. 3.3. Пример операции свертывания ребра и обратного
ему разделения вершин
B
A
H
G
C
D
I
L
J
F
E
K
Рис. 3.4. В верхнем ряду показан ход полной свертки, а в нижнем
полусвертки для одного и того же ребра
В ходе полной свертки, одна из вершин движется в сторону другой до тех пор, пока не совпадет с ней, после чего они заменяются
одной общей вершиной. В ходе полусвертки обе вершины движутся
в сторону центра общего для них ребра, по достижению которого
также заменяются одной вершиной.
Большим преимуществом непрерывных LOD по сравнению
с дискретными, является тот факт, что степень детализации объекта всегда в точности соответствует значению метрики. Это гарантирует, что модель всегда будет обладать достаточной детализацией
для наблюдателя, но при этом иметь наименьшее возможное для
соответствующего алгоритма генерации промежуточных моделей
число полигонов, что снижает потребление ресурсов. Помимо этого данная техника не подвержена эффекту «перепрыгивания», по37
скольку все последовательные модели будут различаться не более
чем на одну вершину.
Недостатки подобного подхода заключаются в том, что значительно вырастает сложность алгоритмов генерации – поскольку
теперь от них требуется, чтобы все порождаемые ими сетки были
корректны с точки зрения наблюдателя, то есть не имели видимых графических артефактов. Помимо этого, непрерывные LOD,
также как и дискретные неприменимы для рендеринга больших
объектов. Большие объекты (например, земная поверхность) будут излишне детализированы даже в тех их частях, что удалены
от наблюдателя. Наконец, поскольку каждая копия одного объекта, использующего непрерывный LOD уникальна, то в памяти
приходится одновременно хранить их все, что может привести
к значительному проигрышу по памяти по сравнению с дискретным LOD.
Видозависимый LOD
По сути своей видозависимый LOD использует идеи непрерывного LOD, но применяет их не к отдельным объектам в модели, а
к текущему полю зрения наблюдателя. Таким образом, он позволяет разным частям одного объекта иметь разные уровни детализации. Так части, расположенные ближе к наблюдателю, будут более
детализированы в отличие от удаленных, а область силуэта будет
более детализована, чем внутренние области объекта.
Ключевой момент, в котором видозависимый LOD превосходит непрерывный, заключается в обработке чрезмерно больших
объектов: той же поверхности земли, например. Помимо этого,
он применим к визуализации данных, полученных, например,
с МРТ(магнитно-резонансная томография) – очень детализованной, но при этом по сути представляющей собой единый объект.
Однако у этого метода есть и серьезный недостаток: он наиболее
требователен к вычислительным ресурсам, поскольку здесь часть
процессов, которые у предыдущих алгоритмов проводились заранее в ходе подготовки модели, должны выполняться динамически
при каждом изменении точки зрения наблюдателя.
К достоинствам видозависимого LOD относят отсутствие «перепрыгивания» по той же причине, что и для непрерывного LOD.
Большие объекты детализируются неоднородно в зависимости удаления их частей от наблюдателя или других метрик. Также данные
алгоритмы обладают высокой точностью соответствия уровня детализации текущим показаниям метрик. Но требуется алгоритм для
генерации спектра уровней детализации, дающий заведомо кор38
Рис. 3.5. Пример видозависимого LOD. Поверхность земли детализована
по разному в зависимости от удаления от наблюдателя (линиями
помечено поле зрения наблюдателя)
ректные с точки зрения наблюдателя результаты (без графических
артефактов). Выполнение вычислений непосредственно в ходе рендеринга может вызвать снижение производительности.
Очевидной идеей для применения данных методик является оптимизация потребления вычислительной мощности, путем снижения детализации удаленных/быстродвижущихся/малозначимых и
т. д. объектов. Освобожденную мощность можно затем потратить на
увеличение числа объектов в сцене или на повышение уровня детализации близких/неподвижных/высокоприоритетных объектов.
Однако существует и альтернативное, гораздо более важное,
применение для механизма LOD. Речь идет о сценах с фиксированным в определенных пределах числом кадров в секунду, то есть
практически обо всех интерактивных сценах, в которых сложность
рендеринга не является постоянной. Любке в своей книге приводит
примеры проблем, которые может вызывать отсутствие ограничения на число кадров в секунду в таких сценах[5]:
– Нарушение восприятия скоростей объектов
– Возможность использовать частоту смены кадров для предсказания каких-либо событий (резкое снижение частоты смены
кадров = увеличение сложности сцены = появление в кадре многочисленных/детализованных объектов)
– В редких случаях резкое изменение FPS даже способно вызывать морскую болезнь у пользователя.
Реализация механизма LOD в Unity3D
Unity3D имеет встроенный механизм уровней детализации,
представляющий собой дискретный статический LOD, основанный
39
на метрике расстояния, заданного в процентном соотношении [1].
Для использования этого механизма в сцену добавляются специальные объекты, т.н. LODGroup, к которым далее присоединяются
представления объекта для разных уровней детализации.
Добавить LODGroup можно через меню Component > Rendering.
В настройках LOD группы выставляются фиксированные значения
% от экранной площади, при которых происходит переключение
с одного уровня на другой.
Как и для любого элемента, включенного в дерево сцены, объекты, включенные в LODGroup имеют собственные параметры в окне
Inspector (см. рис. 3.6).
Рис. 3.6. Инспектор для LOD-объекта
40
Перед созданием LOD необходимо добавить в сцену пустой игровой объект (GameObject > Create Empty или Ctrl+Shift+N), которому и будет привязана LODGroup. В дальнейшем, чтобы избежать
путаницы объектам LODGroup рекомендуется давать звучные имена, например «LOD» (рис. 3.7).
Добавляются новые уровни к группе через контекстное меню
(Insert Before), вызываемое при щелчке правой кнопки по полосе,
отображающей уровни детализации. Для того чтобы удалить уровень детализации используется пункт Delete (см. рис. 3.8).
Перемещая ползунки, разделяющие уровни на этой же полосе,
можно настроить % экранной площади, на которой будет отображаться тот или иной уровень детализации модели. Отметим, также, что последний уровень детализации на полосе настройки, обозначенный «Culled», соответствует полному исчезновению объекта. Этот уровень нельзя удалить с полосы, хотя и можно заставить
объект исчезать только при 0% занимаемой им экранной площади,
когда он и так невидим для камеры.
Рассмотрим работу LODGroup на примере создания простейшей
сцены с геометрическими примитивами, имеющимися в базовом
наборе игрового движка Unity3D. Скриншот сцены приведен на
рисунке 3.9.
Рис. 3.7. Контекстное меню добавления/
удаления уровней детализации
41
Рис. 3.8. Контекстное меню добавления/
удаления уровней детализации
Рис. 3.9. Общий вид 3D-сцены
Для этого воспользуемся объектами двух уровней детализации:
– для LOD нулевого уровня – LOD0, которому соответствует
высокодетализированное представление объекта, возьмем примитив – сферу, число вершин которой равно 525, а число полигонов
соответствует 760 треугольникам;
– для LOD первого уровня – LOD1, т. е. низкодетализированное
представление – куб как предельное упрощение сферы, у которого
12 вершин и 24 полигона.
Таким образом, при правильной настройке механизма LOD
при приближении/удалении от объекта (или при изменении размеров объекта, что также влияет на его экранную площадь) бу42
дем наблюдать визуальный переход от сферы к кубу, что в свою
очередь значительно изменяет число вершин/треугольников
в окне статистики.
На рис. 3.10, 3.11, представленных ниже приведены кадры сцены, в которых работает 2-уровневый LOD для простых геометрических форм.
Рис. 3.10. Нулевой уровень детализации
Рис. 3.11. Уровень детализации 1, число полигонов уменьшилось,
сфера заменилась кубом
43
В игровом режиме (нажата кнопка Play) можно наблюдать статистику изменения количественных характеристик сцены. До применения LOD в тестовой сцене уровень fps довольно низкий 45.8,
65 тыс. вершин и 57 тыс. полигонов (см. рис. 3.13). После применения LODGroup наблюдается резкое изменение данных параметров. Уровень fps возрастает до 70 на нулевом уровне LOD и 118 при
включении LOD 1 уровня. Также наблюдается уменьшение числа
вершин и полигонов(рис. 3.14).
Рис. 3.12. Последний уровень детализации,
объекты не визуализируются
Рис. 3.13. Статистика до применения LOD
44
а)
б)
Рис. 3.14. Статистика после применения LOD
а) LOD 0-уровня; б) LOD 1-уровня
45
Содержание отчета
1. Титульный лист, оформленный в соответствии с ГОСТ.
2. Цель работы и задание на выполнение работы.
3. Описание объектов сцены, подготовленных для применения
LOD, с указанием числа вершин и количества полигонов.
4. Скриншоты подготовленных для применения LOD объектов.
5. Описание порядка действий для настройки элемента управления LODGroup
6. Скриншоты 3D-сцены, демонстрирующие результаты применения LOD.
7. Скриншоты полученной статистики на каждом из уровней
детализации(LOD0, LOD1, LOD2 и т.д.).
8. Анализ результатов и выводы о проделанной работе.
Контрольные вопросы
1. Что такое LOD?
2. Перечислите известные вам методы ускорения процесса визуализации интерактивной 3D-сцены?
3. Что происходит с объектом, если уровень LOD = Culled?
4. На какие группы делятся алгоритмы LOD?
5. Перечислите имеющиеся классификации LOD алгоритмов,
если они существуют.
6. Назовите преимущества и недостатки статических LODалгоритмов.
7. Назовите преимущества и недостатки динамических LODалгоритмов
8. Назовите преимущества и недостатки видозависимого LODалгоритма.
46
Лабораторная работа № 4
«РАЗРАБОТКА ПРОСТОЙ
МНОГОПОЛЬЗОВАТЕЛЬСКОЙ ИГРЫ»
Цель работы: разработка простой многопользовательской игры
на движке Unity3D, создание аватара игрока и настройка системы
«клиент-сервер» на основе мастер-сервера Unity.
Порядок выполнения:
1) Ознакомиться с содержанием раздела «Теоретические сведения».
2) Создать в Unity3D новый проект и пустую сцену.
3) Подготовить игровой уровень.
4) Создать аватара игрока.
5) Подключить скрипт управления аватаром «PlayerMovement»,
приведенный в разделе «Теоретические сведения».
6) Добавить компонент «Rigidbody», подключая тем самым физику к аватару.
7) Проверить работоспособность аватара, запустив сцену в режиме игры.
8) Создать многопользовательский режим взаимодействия аватаров, подключив скрипты, приведенные в разделе «Теоретические сведения».
9) Создать интерфейс игры на основе скрипта «Game Menu»,
приведенного в разделе «Теоретические сведения».
10) Для проверки результата запустить минимум два приложения одновременно на одном компьютере (проект необходимо собрать
как File->Build Settings…->Build). В первом приложении – создать
игру, во втором – подключиться к созданной игре и проверить корректность работы. (Изменения в игре не видны в неактивном окне).
11) Оформить отчет.
Рекомендации по содержанию тестовой сцены:
Игровой уровень должен содержать:
– плоскость(Plane), выступающую в роли поверхности.
– Камера (main Camera)
– источник света (например, Directional Light)
– аватар игрока может быть промоделирован простыми геометрическими объектами.
Теоретические сведения
Существует несколько способов организации многопользовательской игры, основными из которых являются построение одноранговой сети и создание системы «клиент-сервер» [2,7].
47
Первый способ подразумевает распределение нагрузки по обработке данных игры между всеми устройствами сети, при втором –
основная нагрузка ложится на одно или несколько серверных
устройств, на остальных нагрузка сводится к минимуму.
В «чистых» многопользовательских играх основным является второй способ, который не только расширяет пользовательскую базу (так как в игру могут играть люди, имеющие более
слабые сетевые устройства) но и позволяет эффективно решать
многие задачи, трудновыполнимые в одноранговой сети (например, настройка и администрирование игры, технические работы
или борьба с читерами).
Для начала работы необходимо создать в Unity3D новый проект
и пустую сцену. Перед тем, как приступить к разработке аватара
игрока необходимо подготовить игровой уровень (рис. 4.1). В рамках лабораторной работы достаточно создать плоскость (Plane), выступающую в роли поверхности, камеру и источник света (например, Directional Light).
После создания уровня можно приступить к созданию аватара
игрока. Для начала создадим визуальное представление аватара,
например, куб, и разместим его на сцене. Далее в ресурсах проекта необходимо создать типовой объект «Player» (Assets->Create>Prefab) и перетащить куб с панели иерархии (Hierarchy) на его
иконку. Затем куб можно удалить со сцены и вместо него разместить типовой объект (рис. 4.2).
Рисунок 4.1. Создание уровня
48
Рисунок 4.2. Создание типового объекта
Теперь приступим к созданию управления аватаром. Создадим
скрипт «PlayerMovement» (Assests->Create->C# Script). Открываем скрипт и заменяем код на следующий:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
public float speedForward = 2f;
public float speedBackward = 1f;
public float speedJump = 5f;
public float speedTurn = 400f;
void Update() {
InputMovement();
}
private void InputMovement() {
//walk forward
if (Input.GetKey(KeyCode.W)) {
transform.Translate(0, 0, speedForward * Time.deltaTime);
}
//run forward
if (Input.GetKeyDown(KeyCode.LeftShift)) {
speedForward *= 2f;
}
if (Input.GetKeyUp(KeyCode.LeftShift)) {
speedForward *= 0.5f;
49
}
//walk backward
if (Input.GetKey(KeyCode.S)) {
transform.Translate(0, 0,- speedBackward * Time.deltaTime);
}
//Rotate
if (Input.GetKey(KeyCode.D))
transform.Rotate(0, speedTurn * Time.deltaTime, 0);
if (Input.GetKey(KeyCode.A))
transform.Rotate(0, – speedTurn * Time.deltaTime, 0);
//Jump
if (Input.GetKey(KeyCode.Space)) {
transform.Translate(0, speedJump * Time.deltaTime, 0);
}
}
}
Теперь скрипт можно добавить к типовому объекту (Component>Scripts->Player Movement).
Далее добавляем к типовому объекту компонент «Rigidbody»
(Component->Physics->Rigidbody), подключая тем самым физику
к аватару. Настройки компонента приведены на рис 4.3.
Проверяем работоспособность аватара, запустив сцену в режиме
игры (рис. 4.4). Если аватар «слушается» управления, то можно
переходить к разработке многопользовательского режима.
Рисунок 4.3. Компонент «Rigidbody»
50
Рисунок 4.4. Проверка аватара
В начале лабораторной работы аватар был помещен на сцену
вручную, в многопользовательском режиме он должен появляться на сцене при подключении к игре нового пользователя и подчиняться только ему.
Приведенный выше скрипт «PlayerMovement» в многопользовательском режиме будет работать некорректно, так как отсутствует четкое указание скрипту управлять «своим» аватаром, а также
синхронизация между разными аватарами.
Изменим код скрипта на следующий:
using UnityEngine;
using System.Collections;
public class PlayerMovement : MonoBehaviour {
public float speedForward = 2f;
public float speedBackward = 1f;
public float speedJump = 5f;
public float speedTurn = 400f;
private float lastSyncTime = 0f;
private float syncDelay = 0f;
private float syncTime = 0f;
private Vector3 syncStartPosition = Vector3.zero;
private Vector3 syncEndPosition = Vector3.zero;
private Quaternion syncStartRotation = Quaternion.identity;
private Quaternion syncEndRotation = Quaternion.identity;
51
void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo
info) {
Vector3 syncPosition = Vector3.zero;
Vector3 syncVelocity = Vector3.zero;
Quaternion syncRotation = Quaternion.identity;
if (stream.isWriting) {
syncPosition = transform.position;
stream.Serialize(ref syncPosition);
syncVelocity = rigidbody.velocity;
stream.Serialize(ref syncVelocity);
syncRotation = transform.rotation;
stream.Serialize(ref syncRotation);
} else {
stream.Serialize(ref syncPosition);
stream.Serialize(ref syncVelocity);
stream.Serialize(ref syncRotation);
syncTime = 0f;
syncDelay = Time.time – lastSyncTime;
lastSyncTime = Time.time;
syncEndPosition = syncPosition + syncVelocity * syncDelay;
syncStartPosition = transform.position;
syncEndRotation = syncRotation;
syncStartRotation = transform.rotation;
}
}
void Awake(){
lastSyncTime = Time.time;
}
void Update() {
if (networkView.isMine) {
InputMovement();
} else {
SyncedMovement();
}
}
52
private void InputMovement() {
// walk forward
if (Input.GetKey(KeyCode.W)) {
transform.Translate(0, 0, speedForward * Time.deltaTime);
}
//run forward
if (Input.GetKeyDown(KeyCode.LeftShift)) {
speedForward *= 2f;
}
if (Input.GetKeyUp(KeyCode.LeftShift)) {
speedForward *= 0.5f;
}
//walk backward
if (Input.GetKey(KeyCode.S)) {
transform.Translate(0, 0,- speedBackward * Time.deltaTime);
}
//Rotate
if (Input.GetKey(KeyCode.D))
transform.Rotate(0, speedTurn * Time.deltaTime, 0);
if (Input.GetKey(KeyCode.A))
transform.Rotate(0, – speedTurn * Time.deltaTime, 0);
//Jump
if (Input.GetKey(KeyCode.Space)) {
transform.Translate(0, speedJump * Time.deltaTime, 0);
}
}
private void SyncedMovement() {
syncTime += Time.deltaTime;
transform.position
=
Vector3.Lerp(syncStartPosition,
syncEndPosition, syncTime / syncDelay);
transform.rotation = Quaternion.Inverse(Quaternion.Lerp(syncStart
Rotation, syncEndRotation, syncTime / syncDelay));
}
}
К аватару добавляем компонент «Network View» (Component>Miscellaneous->NetworkView). В поле «Observed» должен быть
указан скрипт «Player Movement»(рис.4.5).
Удаляем аватар со сцены и размещаем на ней пустые объекты
«Admin Spawn» и «Player Spawn» (GameObject->Create Empty).
53
Рисунок 4.5. Компонент «Network View»
Эти объекты отвечают за появление персонажей администратора и
игроков соответственно при запуске игры.
Создаем скрипт «ServerManager», содержащий в себе логику
работы сервера. Открываем скрипт и заменяем код на следующий:
using UnityEngine;
using System.Collections;
public class ServerManager : MonoBehaviour {
public GameObject adminPrefab;
private Vector3 adminPosition;
public void StartServer(string game_type, string game_name) {
Network.InitializeServer(5, 25000, !Network.HavePublicAddress());
MasterServer.RegisterHost(game_type, game_name);
}
void OnServerInitialized() {
SpawnAdmin();
}
void SpawnAdmin() {
adminPosition = new Vector3(transform.position.x + int.Parse
(Network.player.ToString()), transform.position.y, transform.position.z);
Network.Instantiate(adminPrefab,
adminPosition,
transform.
rotation, 0);
}
void OnPlayerDisconnected(NetworkPlayer player) {
Network.RemoveRPCs(player, 0);
Network.DestroyPlayerObjects(player);
}
}
54
Добавляем к объекту «Admin Spawn» вышеприведенный скрипт.
Далее создаем скрипт «ClientManager», содержащий в себе логику работы клиента. Открываем скрипт и заменяем код на следующий:
using UnityEngine;
using System.Collections;
public class ClientManager : MonoBehaviour {
public GameObject playerPrefab;
private Vector3 playerPosition;
public void JoinServer(HostData host_data){
Network.Connect(host_data);
}
void OnConnectedToServer() {
SpawnPlayer();
}
[RPC]
void SpawnPlayer() {
playerPosition = new Vector3(transform.position.x + int.Parse
(Network.player.ToString()), transform.position.y, transform.position.z);
Network.Instantiate(playerPrefab,
playerPosition,
transform.
rotation, 0);
}
[RPC]
void OnDisconnectedFromServer( NetworkDisconnection info ) {
Network.DestroyPlayerObjects( Network.player );
}
}
Добавляем к объекту «Player Spawn» вышеприведенный скрипт.
В поля «Player Prefab» и «Admin Prefab» соответствующих
скриптов перетягиваем аватар (рис 4.6.)
Рисунок 4.6. Компонент «Client Manager»
55
Теперь осталось лишь создать интерфейс. Создаем скрипт «Game
Menu», открываем и добавляем в него следующий код:
using UnityEngine;
using System.Collections;
public class GameMenu : MonoBehaviour {
public GUIStyle style;
public Transform serverManager;
public Transform clientManager;
private const int ST_MENU = 0;
private const int ST_QUIT = 1;
private const int ST_GAME = 2;
private const int MP_NONE = 0;
private const int MP_MAIN = 1;
private const int MP_FIND = 2;
private const int MP_GAME = 3;
private int state;
private int page;
private bool inGame = false;
public int buttonHeight = 30;
public int buttonWidth = 160;
public int buttonSpace = 5;
public int buttonPosLeft = 50;
public int buttonPosTop = 75;
private Rect menuBox = new Rect(0, 0, 260, Screen.height);
private HostData[] hostList;
private bool isRefreshing = false;
private ServerManager server;
private ClientManager client;
private const string gameType = «Fortress Battle Game»;
private const string gameName = «Fortress Battle Room»;
void Start () {
state = ST_MENU;
page = MP_MAIN;
56
server = serverManager.GetComponent<ServerManager>();
client = clientManager.GetComponent<ClientManager>();
}
void Update () {
//Возвращение на предыдущую страницу
if (Input.GetKeyDown(KeyCode.Escape)){
switch (state){
case ST_MENU:
switch (page) {
case MP_MAIN:
if (inGame){
state = ST_GAME;
page = MP_NONE;
}
break;
case MP_FIND:
page = MP_MAIN;
break;
case MP_GAME:
if(inGame)
page = MP_NONE;
break;
case MP_NONE:
if(inGame)
page = MP_GAME;
break;
}
break;
case ST_GAME:
state = ST_MENU;
page = MP_GAME;
break;
}
}
//Обновление списка игр
if (isRefreshing && MasterServer.PollHostList().Length > 0) {
isRefreshing = false;
hostList = MasterServer.PollHostList();
}
}
void OnGUI(){
switch (state){
case ST_MENU:
switch (page){
57
case MP_MAIN:
DrawMainMenuPage();
break;
case MP_GAME:
DrawGameMenuPage();
break;
case MP_FIND:
DrawFindGamesMenuPage();
break;
};
break;
case ST_QUIT:
Application.Quit();
break;
}
}
void DrawMainMenuPage(){
GUI.Box (menuBox, «Новая игра»);
Rect start_game = new Rect(buttonPosLeft, buttonPosTop,
buttonWidth, buttonHeight);
Rect find_games = new Rect (buttonPosLeft, buttonPosTop + buttonHeight + buttonSpace, buttonWidth, buttonHeight);
Rect quit = new Rect(buttonPosLeft, Screen.height – buttonPosTop –
buttonHeight, buttonWidth, buttonHeight);
if (GUI.Button(start_game, “Создать игру”)){
state = ST_GAME;
page = MP_NONE;
inGame = true;
server.StartServer(gameType, gameName);
}
if (GUI.Button(find_games, “Найти игры”))
page = MP_FIND;
if (GUI.Button(quit, “Выход”)) {
state = ST_QUIT;
page = MP_NONE;
Network.Disconnect();
MasterServer.UnregisterHost();
}
}
void DrawGameMenuPage(){
GUI.Box (menuBox, “Игра”);
Rect resume_game = new Rect(buttonPosLeft, buttonPosTop,
buttonWidth, buttonHeight);
Rect quit_game = new Rect(buttonPosLeft, buttonPosTop +
buttonHeight + buttonSpace, buttonWidth, buttonHeight);
58
if (GUI.Button(resume_game, “Продолжить игру”)){
state = ST_GAME;
page = MP_NONE;
}
if (GUI.Button(quit_game, “Покинуть игру”)) {
state = ST_MENU;
page = MP_MAIN;
Network.Disconnect();
MasterServer.UnregisterHost();
}
}
void DrawFindGamesMenuPage(){
GUI.Box (menuBox, “Поиск игр”);
Rect refreshGames = new Rect(buttonPosLeft, buttonPosTop,
buttonWidth, buttonHeight);
Rect back = new Rect(buttonPosLeft, Screen.height – buttonPosTop –
buttonHeight, buttonWidth, buttonHeight);
if (GUI.Button(refreshGames, “Обновить”))
RefreshHostList();
if (hostList != null)
for (int i = 0; i < hostList.Length; i++)
if (GUI.Button (new Rect (buttonPosLeft, buttonPosTop +
buttonHeight * (1 + i) + buttonSpace * (1 + i), buttonWidth, buttonHeight),
hostList [i].gameName)) {
state = ST_GAME;
page = MP_NONE;
client.JoinServer(hostList[i]);
inGame = true;
}
if (GUI.Button(back, “Назад”)){
page = MP_MAIN;
}
}
void RefreshHostList() {
if (!isRefreshing){
isRefreshing = true;
MasterServer.RequestHostList(gameType);
}
}
}
Создаем пустой объект «Menu» и добавляем в него вышеприведенный скрипт. В полях «Server Manager» и «Client
59
Manager» указываем объекты «Admin Spawn» и «Player Spawn»
соответственно(рис. 4.7).
Проверяем получившийся результат (рис. 4.8 – 4.9). Для проверки достаточно запустить минимум два приложения одновременно на
одном компьютере, для чего проект необходимо собрать (File->Build
Settings…->Build). Запускаем приложения, в первом – создаем игру,
во втором – подключаемся к созданной игре, удостоверяемся, что все
работает корректно. (Изменения в игре не видны в неактивном окне!)
Рисунок 4.7. Компонент «Client Manager»
Рисунок 4.8. Меню «Поиск игр»
60
Рисунок 4.9. Результат
Содержание отчета
1) Титульный лист, оформленный в соответствии с ГОСТ.
2) Цель работы и задание на выполнение работы.
3) Поэтапное описание выполнения работы со скриншотами результатов
4) Описание алгоритмов работы скриптов
5) Анализ результатов и выводы о проделанной работе.
Контрольные вопросы:
1) Что представляет собой аватар игрока?
2) Какие новые качества добавляет аватару компонент
«Rigidbody»?
3) Какой скрипт обеспечивает управление аватаром в однопользовательском режиме работы?
4) Как проверить работоспособность аватара?
5) Какие компоненты Unity3D отвечают за появление аватаров
администратора и игроков в многопользовательской игре?
6) Что является основой для разработки пользовательского интерфейса?
7) Как проверить работу многопользовательской игры с помощью одного компьютера?
61
Лабораторная работа № 5
«РАЗРАБОТКА ИНТЕЛЛЕКТУАЛЬНОГО АВАТАРА»
Цель работы: разработка простого интеллектуального аватара
(бота) для игры, реализованной в лабораторной работе № 4.
Порядок выполнения
1) Открыть проект, созданный в лабораторной работе №4.
2) Создать визуальное представление(заготовку)бота, отличное
от представления аватара игрока.
3) Добавить компонент «Rigidbody», отвечающий за физическое
взаимодействие объекта с окружающим миром.
4) «Научить» бота перемещаться по игровому уровню, используя поиск пути с помощью навигационной модели (см. раздел «Теоретические сведения»).
5) «Научить» бота реагировать на перемещение игрока (см. раздел «Теоретические сведения»).
6) Откорректировать характеристики аватара игрока, опираясь
на реакцию бота и сведения, приведенные в разделе «Теоретические сведения».
7) Создать скрипт «BotAI», реализующий систему принятия решений и добавить к боту.
8) Для проверки результата работы запустить игру. Если бот
преследует близко подошедшего игрока, то лабораторная работа
выполнена.
9) Оформить отчет.
Теоретические сведения
Под искусственным интеллектом в играх подразумевается программа, благодаря которой контролируемые компьютером элементы способны принимать разумные решения, выбирая один из нескольких вариантов разрешения возникшей ситуации [2,8].
Общий состав системы игрового искусственного интеллекта
(ИИ) приведен на рисунке 5.1:
– Восприятие бота может быть описано как набор неких элементов игрового мира, на которые бот должен реагировать. Простейший
пример – положение аватара игрока или других ботов. Фактически
система восприятия представляет входные данные для системы принятия решений.
– Система принятия решений является важнейшей частью
системы ИИ. Она определяет действия бота на внешние раздражители.
62
Игра
Загрузка
данных
Система ИИ
Инициализация
Обновление
Принятие
решений
Система
восприятия
Навигация
Рисунок 5.1. Общий состав системы игрового ИИ
– Основной задачей механизма навигации является поиск кратчайшего пути из точки А в точку В.
Реализация восприятия бота сильно зависит от игрового движка, система принятия решений в играх обычно реализуется с помощью продукционной модели или модели, основанной на правилах
(RBS – Rule-Based System).
RBS состоит из следующих компонентов:
– Набор продукционных правил или продукций. Продукция –
это пара «ЕСЛИ условие, ТО действие». Условная часть правила –
это образец, который определяет, когда это правило может быть
применено для решения какого-либо этапа задачи. Часть действия
определяет соответствующий шаг в решении задачи.
– Рабочая память содержит описание текущего состояния мира
в процессе рассуждений. Если условие некоторого правила соответ63
ствует содержимому рабочей памяти, то может выполняться действие, связанное с этим условием.
– Цикл «распознавание-действие». Рабочая память инициализируется начальным описанием задачи. Текущее состояние решения задачи представляется набором образцов в рабочей памяти. Эти
образцы сопоставляются с условиями продукционных правил, что
порождает подмножество правил вывода, называемое конфликтным множеством. Выбирается и выполняется одна из продукций
конфликтного множества (разрешение конфликта). При этом изменяется содержание рабочей памяти. После того как выбранное
правило сработало, цикл управления повторяется для модифици-
Рисунок 5.2. Метод навигационной модели
64
рованной рабочей памяти. Процесс заканчивается, если содержимое рабочей памяти не соответствует никаким условиям.
RBS, как и прочие подобные системы, не являются идеальными. Их основные недостатки проявляется при большом количестве
правил – сложность поиска соответствия растет по линейному закону, разрешение конфликтов может потребовать реализации специальных алгоритмов, среди правил могут возникать противоречия.
В тоже время RBS интуитивно понятны и просты для реализации.
Учитывая узкую функциональность бота в рамках задачи игрового
ИИ, количество правил невелико, и, следовательно, использование
данной модели предпочтительно.
Существует несколько способов создания механизма навигации
бота. В Unity3D реализован метод навигационной модели(рис. 5.2).
Суть метода состоит в генерации так называемых «путевых» точек
используя полигоны, составляющие трехмерную модель игрового
уровня. После генерации бот может перемещаться между этими
точками, используя специальные алгоритмы поиска пути (например, А*). В тоже время необходимо учитывать несовершенство
механизмов генерации – создание лишних точек в ненужных местах – и заранее оптимизировать уровень перед генерацией.
Описание процесса разработки
интеллектуального аватара (бота)
Открываем проект, созданный в ходе предыдущей лабораторной
работы. Создаем визуальное представление бота, отличное от такового у аватара игрока. Создаем типовой объект (Prefab), перетаскиваем модель с панели иерархии (Hierarchy) на иконку типового
объекта, удаляем модель.
Таким образом, у нас имеется заготовка бота. Теперь к нему, как
и к аватару игрока необходимо подключить компонент «Rigidbody»
(Component->Physics->Rigidbody), отвечающий за физическое взаимодействие объекта с окружающим миром. Настройки компонента приведены на рис 5.3.
Следующий шаг – «научить» бота перемещаться по уровню, используя поиск пути с помощью навигационной модели. Для этого
сначала нужно подключить компонент «NavMeshAgent» к боту
(Component->Navigation->NavMeshAgent). Затем создаем саму модель на основе нашей поверхности. Для этого указываем в настройках поверхности атрибут Static (рис. 5.4).
Далее вызываем панель «Navigaion» (Window->Navigaion) и запускаем процесс генерации модели (кнопка Bake). Результат должен соответствовать рис. 5.5.
65
Рисунок 5.3. Компонент «Rigidbody»
Рисунок 5.4. Атрибут «Static»
Рисунок 5.5. Сгенерированная навигационная модель
Создадим скрипт «BotMovement» и добавим в него следующий код:
using UnityEngine;
using System.Collections;
public class BotMovement : MonoBehaviour {
66
private Vector3 movementTarget;
private NavMeshAgent navMeshAgent;
private float distanceTorTarget;
public float maxDistanceToTarget = 2.0f;
private Vector3 initialPosition;
void Start() {
navMeshAgent = GetComponent<NavMeshAgent>();
movementTarget = initialPosition = transform.position;
}
void Update(){
distanceTorTarget = Vector3.Distance(movementTarget, transform.
position);
if(distanceTorTarget > maxDistanceToTarget) {
navMeshAgent.SetDestination(movementTarget);
} else {
navMeshAgent.Stop();
}
}
public void SetMovementTarget(Vector3 target) {
movementTarget = target;
}
public Vector3 getInitialPosition() {
return initialPosition;
}
}
Добавляем скрипт к боту. Теперь «научим» бота реагировать на
перемещение игрока. Добавим к боту «область реакции» представляющую собой компонент «Sphere Collider» (Component->Physics>Sphere Collider), настроенный как триггер (рис. 5.6).
Рисунок 5.6. Компонент «Sphere Collider»
67
Далее создаем новый скрипт «BotTrigger», определяющий присутствие аватара игрока через зону реакции и так же добавим к боту:
using UnityEngine;
using System.Collections;
public class BotTrigger : MonoBehaviour {
private BotAI AI;
private Transform intruder;
void Start () {
AI = GetComponent<BotAI>();
}
private void OnTriggerEnter(Collider other){
if (other.CompareTag(«Player»)) {
AI.setDisturbedState(true);
intruder = other.transform;
}
}
private void OnTriggerExit(Collider other) {
if (other.CompareTag(«Player»)) {
AI.setDisturbedState(false);
}
}
public Transform getIntruder() {
return intruder;
}
}
Рисунок 5.7. Тэг «Player»
68
Как видно из кода скрипта, бот «реагирует» только на объекты
с тегом «Player». Добавим этот тег к аватару игрока (рис. 5.7).
И последний шаг – создание скрипта «BotAI», реализующего
систему принятия решений:
using UnityEngine;
using System.Collections;
public class BotAI : MonoBehaviour {
private BotTrigger trigger;
private BotMovement movement;
private bool stateWounded;
private bool stateDisturbed;
void Start () {
trigger = transform.GetComponent<BotTrigger>();
movement = transform.GetComponent<BotMovement>();
stateDisturbed = false;
}
void Update () {
if(stateDisturbed) {
Transform intruder = trigger.getIntruder();
movement.SetMovementTarget(intruder.position);
}
if(!stateDisturbed) {
movement.SetMovementTarget(movement.getInitial
Position());
}
}
public void setDisturbedState(bool state) {
stateDisturbed = state;
}
}
Добавляем скрипт к боту и запускаем игру(рис. 5.8). Если бот
преследует близко подошедшего игрока, то лабораторная работа
выполнена правильно.
69
Рис. 4.9. Результат
Рис. 5.8. Результат
70
Содержание отчета
1) Титульный лист, оформленный в соответствии с ГОСТ.
2) Цель работы и задание на выполнение работы.
3) Поэтапное описание выполнения работы со скриншотами результатов
4) Описание алгоритмов работы скриптов
5) Анализ результатов и выводы о проделанной работе.
Контрольные вопросы:
1) Что представляет собой интеллектуальный аватар – бот ?
2) Какие новые качества добавляет боту компонент «Rigidbody»?
3) Какой компонент Unity3D задает «область реакции» бота?
4) Какой скрипт обеспечивает интеллектуальное поведение бота?
5) Как проверить реакцию бота на действия аватара игрока?
РЕКОМЕНДУЕМАЯ ЛИТЕРАТУРА
1. Unity (игровой движок). URL: https://ru.wikipedia.org/wiki/
Unity/(игровой движок).
2. Официальный сайт Unity. URL: http://unity3d.com/unity.
3. Основы работы в UNITY3D: метод. указ. к выполнению
лаборатор. работ для студ. направления 230100.68 – «Информатика
и вычислительная техника»/ сост. А. Н. Жирнов, А. В. Коновалов,
А. А. Преображенский; под ред. А. В. Никитина. СПб.: ГУАП,
2014. 63 с.
4. Эйнджел Э. Интерактивная трехмерная графика. М.: Вильямс,
2001. 592 с.
5. Luebke D., Reddy M., Cohen J. D. et al. Level of Detail for 3D
graphics // Morgan Kaufmann Publishers, 2003. 390 p.
6. Hoppe H. Automated video looping with progressive dynamism.
URL: http://research.microsoft.com/en-us/um/people/hoppe/.
7. Alan R. Stagner. Unity Multiplayer Games: Build engaging,
fully functional, multiplayer games with Unity engine. - Published by
Packt Publishing Ltd., BIRMINGHAM – MUMBAI, 2013.
8. Aung Sithu Kyaw, Clifford Peters, Thet Naing Swe. Unity 4.x
Game AI Programming. Published by Packt Publishing Ltd., BIRMINGHAM – MUMBA, 2013.
71
Содержание
Введение...................................................................................
3
Лабораторная работа № 1. «Ознакомление с функциональными
возможностями управления характеристиками камеры» ................
6
Лабораторная работа № 2. «Ознакомление с функциональными
возможностями управления пирамидой видимости».......................
19
Лабораторная работа № 3. «Изучение механизма
уровней детализации»................................................................
31
Лабораторная работа № 4. «Разработка простой
многопользовательской игры».....................................................
47
Лабораторная работа № 5. «Разработка
интеллектуального аватара»........................................................
62
Рекомендуемая литература.........................................................
71
Документ
Категория
Без категории
Просмотров
1
Размер файла
6 027 Кб
Теги
polyshkina
1/--страниц
Пожаловаться на содержимое документа