игры “Cube rube” - факультете информатики ТГУ.

advertisement
Федеральное агентство по образованию
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
Факультет информатики
Кафедра прикладной информатики
УДК 004.4:004.7
ДОПУСТИТЬ К ЗАЩИТЕ В ГАК
Зав. кафедрой, проф., д. т. н.
__________________C.П.Сущенко
«____»_________________2010 г.
Шалдов Егор Андреевич
РАЗРАБОТКА 3D - ИГРЫ “Cube Rube”
Дипломная работа
Научный руководитель,
старший разработчик
компании “Вита менеджмент”
Поздеев А.Г.
Исполнитель:
студ. гр 1451
Шалдов Е. А.
Электронная версия дипломной работы помещена
в электронную библиотеку. Файл
Администратор
Томск – 2010
Реферат
Дипломная работа 51стр, 13 рис, 10 источников.
3D СЦЕНА, ТЕКСТУРА, ИГРОВОЙ ОБЪЕКТ, UNITY3D, ШЕЙДЕР,
ФИЗИЧЕСКАЯ МОДЕЛЬ, СКРИПТ, C#, iPhone, iPod touch
Объект исследования –3D - игра, архитектура системы.
Цель работы – создание игры, удовлетворяющей требованиям
начальной спецификации, исследование технологий создания 3D - игр, а
также приемов программирования для iPhone.
Метод
исследования
–
теоретического
исследование
и
практическая реализация.
Область применения – Организации, для распространения на
App Store
Результаты работы – В результате проделанной работы, мной
была создана 3D - игра “Cube-Rube”, которая полностью удовлетворяет
начальной
спецификации.
Также
было
проведено
исследование
возможностей iPhone, а именно производительности при работе с 3D
графикой. Был получен большой опыт в разработке
iPhone.
2
приложений для
Оглавление
Реферат ...........................................................................................................................................2
Оглавление .....................................................................................................................................3
Введение .........................................................................................................................................6
1 Аналитический обзор предметной области .............................................................................8
1.1 Обзор 3D - игры «Cube-Rube»................................................................................................8
1.2 Обзор среды разработки .......................................................................................................10
1.2.1 Технические характеристики ............................................................................................11
1.2.2 Достоинства и недостатки .................................................................................................11
1.2.3 Особенности Unity для iPhone...........................................................................................12
2 Проектирование приложения ..................................................................................................13
2.1 Физическая модель куба .......................................................................................................13
2.1.1 Модель куба и её построение ............................................................................................13
2.1.2 Вращение куба вокруг своего центра ...............................................................................15
2.1.3 Вращение слайсов ..............................................................................................................15
2.2 Работа с текстурами ..............................................................................................................17
2.2.1 Термины и основные принципы .......................................................................................17
2.2.2 Загрузка текстур на грани куба .........................................................................................19
2.2.3 Представление текстур в памяти. Класс ListTexture.......................................................20
2.2.4 Заполнение массива текстур..............................................................................................21
2.2.5 Шейдер и суммирование альфа слоя для выделения......................................................21
2.3 Пользовательский графический интерфейс (GUI) .............................................................21
2.3.1 Основные принципы работы GUI в Unity3D ...................................................................22
2.3.2 Машина состояний .............................................................................................................23
2.3.3 Отображение кнопок и меню ............................................................................................24
2.3.4 Окно выбора текстур..........................................................................................................25
2.4 Звук .........................................................................................................................................27
3
2.4.1 Принцип и особенности работы со звуком в Unity3D ....................................................28
2.4.2 Работа со звуком. Класс SoundManager ...........................................................................28
2.5 Фотографирование и использование пользовательских изображений ............................29
2.5.1 Использование нативного кода в Unity3D .......................................................................30
2.5.2 Принцип работы класса PhotoScript .................................................................................30
2.5.3 Принцип работы нативного класса...................................................................................31
2.6 Игровая статистика................................................................................................................32
2.6.1 Правила победы и подсчета игровой статистики............................................................32
2.6.2 Окно игровой статистики с его особенностью ................................................................32
2.6.3 Сохранение и загрузка игровой статистики.....................................................................33
2.7 Использование Интернета для загрузки изображений ......................................................33
2.7.1 Принципы работы с Интернетом в Unity3D ....................................................................33
2.7.2 Описание ресурса Panoramio .............................................................................................34
2.7.2.1 API panoramio...................................................................................................................34
2.7.2.2 Формат JSON ...................................................................................................................35
2.7.2.3 Принцип работы скрипта PanaramioRequest.................................................................36
2.7.3 Загрузка изображений с сервера VitaSW .........................................................................38
2.7.3.1 Принцип работы скрипта VitaServerRequest.................................................................38
2.8 Сохранение и загрузка сцены...............................................................................................38
2.8.1 Принципы сохранения объектов.......................................................................................39
2.8.2 Принцип работы скрипта StartScript.................................................................................39
2.8.3 Сохранение..........................................................................................................................39
2.8.4 Загрузка ...............................................................................................................................40
3 Улучшение производительности и устойчивости программы.............................................41
3.1 Характеристики iPhone .........................................................................................................41
3.2 Проблема производительности ............................................................................................43
3.2.1.Уменьшение количества полигонов .................................................................................43
3.2.2 Модернизация поворота куба............................................................................................44
4
3.2.3.Уменьшение количества DrawCalls ..................................................................................44
3.3 Проблема нехватки оперативной памяти............................................................................45
3.3.1 Реализация механизма свопинга .......................................................................................46
3.3.2 Модернизация алгоритма фотографирования .................................................................50
Заключение...................................................................................................................................51
Список используемых источников ............................................................................................52
5
Введение
Мобильные устройства постепенно захватывают мир. Наличие
ноутбука, нетбука или КПК у рядового человека на сегодняшний день
является обычным делом. Поэтому нет ничего удивительного в том, что все
больше и больше программного обеспечение требуется именно для таких
устройств. В последнее время многие люди хотят видеть полноценный
персональный компьютер у себя в КПК.
И мировые производители
стремятся воплотить это желание в жизнь. К полноценному функционалу
можно отнести такие задачи как сетевые программы, 3D - игры, GIS и т.д..
Но все же на данный момент производительность карманных устройств
сильно уступает персональным компьютерам, поэтому необходимо
применять особые алгоритмы для разработки приложений, а также методы
программирования.
Одним из самых распространенных карманных устройств являются
устройства фирмы Apple: iPod и iPhone. Они служат для прослушивания
музыки, телефонных звонков, отправки смс и электронной почты, а также
многого другого. Многие люди играют в игры на них, поэтому данный
рынок ПО развивается очень быстро. Конкуренция порождает
более
изощренные и красочные игры. Новым этапом в разработке игр для
карманных устройств стали полноценные 3D - игры, в которых
используются шейдеры материалов,
тени и большое количество 3D
объектов. Но так как быстродействие, оперативная память, скорость чтения
с диска у iPod и IPhone не очень велики, существуют ограничения на
создание 3D - игр.
Компании “VItaSW” была поставлена задача создание 3D - игры для
iPod и iPhone – “Cube Rube”. Но в отличие от обычной игры размерность
кубика должна была увеличиваться до 6х6. Также было необходимо
реализовать
работу с Интернетом для этого приложения. Но решить
поставленную задачу “в лоб” не получилось, разработчикам пришлось
6
столкнуться сразу с несколькими проблемами производительности iPhone и
IPod:
1.
Скорость работы графического ядра устройства
2.
Объем оперативной памяти для одного запущенного приложения
3.
Скорость чтения с диска устройства
4.
Скорость процессора
5.
Пропускная способность GPS
Для разработки 3D части был взят движок Unity 1.6 for iPhone.
Данный движок позволяет программировать 3D сцены именно для iPhone,
iPod а также iPad. Языком программирование для этой среды был выбран
C# как основной скриптовый язык для 3D сцены, Java script как
вспомогательный, а также Objective C для обращения к операционной
системы iPhone ввиду того, что данный язык является стандартом Apple.
Первая часть дипломной работы посвящена разработке приложения
“Cube-Rube”, в которой рассматриваются аспекты работы с Unity и
операционной системой
iPhone. Вторая часть дипломной работы
посвящена исследованию возможностей iPhone, а также оптимизации
приложения.
7
1 Аналитический обзор предметной области
Кубик Рубика – механическая головоломка, изобретенная в 1974 году
венгерским скульптором и преподавателем архитектуры Эрнё Рубиком.
Головоломка представляет собой пластмассовый куб составленный из 26
кубиков меньшего размера, способных вращаться вокруг невидимых
снаружи осей. Каждый из 9 квадратов на каждой стороне кубика окрашен в
один из 6 цветов. Считается, что Кубик Рубика – лидер среди игрушек по
общему количеству продаж: по всему миру продано порядка 350 млн
Кубиков Рубика, как оригинальных, так и различных вариаций.
1.1 Обзор 3D - игры «Cube-Rube»
Данная игра представляет собой симулятор обычной игры кубик рубик, в которой необходимо собрать кубик 3х3, предварительно его
перемешав. Кубик считается собранным, когда на каждой стороне
окажутся маленькие кубики только одного цвета. В отличие от обычной
игры в данной программе динамически задается размерность куба от 2х2 до
6х6. Также помимо обычной цветовой схемы пользователь может
накладывать картинки на стороны куба из библиотеки картинок или
фотографии из домашнего каталога iPhone.
Игра написана на движке Unity for iPhone 1.6. Данный движок
предоставляет быстрое и удобное
программирование 3D сцен. Всё
взаимодействие заключается в отработке скриптов, которые прикреплены к
игровым
объектам.
прикрепленных
У
каждого
объекта
может
быть
несколько
скриптов. За один кадр–фрейм программа выполняет
метод Update() в каждом активном скрипте, а также перерисовывает сцену
в зависимости от изменений.
В игре существуют 3 основных объекта:
8
•
Gameobject – это сам куб, а точнее родительский объект к
которому прикрепляются все маленькие кубики из которых состоит
большой куб.
•
Game Camera – это основная и единственная камера, через
которую пользователь смотрит на сцену.
•
ScriptStorage – это пустой объект, который не отрисовывается на
сцене, и к которому прикреплены игровые скрипты, которые нельзя
ассоциировать с конкретным игровым объектом.
В игре существуют следующие скрипты (основные):
•
CubeScript
•
myGUI
•
CubeGlobalVar
•
TextureScript
•
PhotoScript
•
Stats
В каждом скрипте содержится один или несколько классов, если
класс унаследован от MonoBehavior и может прикрепляться к игровым
объектам, то его имя должно совпадать с название скрипта.
9
1.2 Обзор среды разработки
Unity - это мультиплатформенный инструмент для разработки 3D игр. Но также возможно написание и 2D-игр. Unity содержит полный набор
качеств профессионального приложения и "совсем случайно" содержит
наиболее мощный движок по эту сторону миллиона долларов. Рождением
данной программы можно считать июнь 2005 года, когда было
представлена миру первая версия (июнь 2005,Unity 1.0.1.). И с тех пор
развитие данного продукта не останавливается ни на минуту. На
сегодняшний день доступна 3 версия, в которой реализованы все самые
последние 3D технологии [1]. На рисунке 2.1 представлено окно редактора
Unity.
Рис 2.1 - Окно редактора Unity
Количество
пользователей
данного
приложение
растет
в
геометрической последовательности, 16 февраля 2010 года количество
зарегистрированных пользователей Unity 3D превысило 100 тысяч[2].
10
Данный движок предоставляет быстрый и гибкий способ портирования
своего приложения практически на любую популярную операционную
систему. Важной особенностью данного движка, из-за которого он так
популярен, это возможность запуска своего приложения на любом
Интернет браузера, необходимо просто установить плагин – Unity Web
Player, а также возможность разработки для iPhone, iPod touch, iPad, а также
в 3 версии добавлена поддержка Android[1].
1.2.1 Технические характеристики
Перечень технических характеристик:
1.
Игровой движок полностью интегрирован в среду разработки,
что позволяет прямо в редакторе тестировать игру;
2.
Работа с ресурсами возможна через простой drag&drop.
Интерфейс редактора настраиваем;
3.
Поддержка DirectX и OpenGL;
4.
Реализована система наследования объектов;
5.
Поддержка импорта из очень большого количества форматов;
6.
Встроенный генератор ландшафтов;
7.
Встроенная поддержка сети;
8.
Есть решение для коллективной разработки - Asset Server.
9.
Также можно использовать свой любимый способ контроля
версий. Tortoise SVN или Source Gear к примеру.
1.2.2 Достоинства и недостатки
Перечень достоинств и недостатков
ƒ
«+»широкие возможности импорта;
ƒ
«+» кроссплатформенность;
ƒ
«+» гибкая ценовая категория и невысокие цены;
11
ƒ
«-» в версии 2.6 используется устаревшая версия PhysX, без
симуляции жидкостей, мягких тел и тканей, начиная с 3 версии, этот
недостаток решен.
1.2.3 Особенности Unity для iPhone
•
Бесшовная организация рабочего процесса - Билд для iPhone -
это полный XCode проект, который сразу же можно использовать[3].
•
Высокопроизводительные скрипты - во время создания билда
JavaScript и C# компилируются в нативный ассемблерный код ARM. Это
дает средний прирост производительности в 20-40 раз по сравнению с
интерпретируемыми языками[3].
•
Высокопроизводительная отрисовка сетки (Mesh Rendering) -
Unity использует упакованные форматы для мешей, которые позволяют
выжать максимум из возможной производительности iPhone[3].
•
Удаление перекрываемых поверхностей (Occlusion culling)[3].
•
Эмуляция шейдеров - имитирование графических возможностей
iPhone прямо внутри Редактора Unity для быстрого создания WYSIWYGпрототипов. Unity полностью поддерживает возможности iPhone в
мультитекстурировании[3].
•
Алгоритм сжатия текстур PRVTC[3].
12
2 Проектирование приложения
Так как приложение реализовано как взаимодействие разных
объектов с 3D сценой и другими объектами, а также отработкой скриптов,
прикрепленных к этим объектам, то обыкновенная парадигма GUI
приложений не подходит, так как у нас есть не только пользователь,
влияющий на изменения приложения. Поэтому приложение построено как
взаимодействие игровых объектов, которые инкапсулируют каждый свою
логику.
2.1 Физическая модель куба
За физическую модель куба отвечает скрипт CubeScript. В нем
описаны методы для построения куба и его вращения.
2.1.1 Модель куба и её построение
Куб достаточно простой 3-х мерный геометрический объект, стороны
которого равны, а углы между сторонами равны 90 градусов. В нашем
случае куб должен совершать вращения своими частями-слайсами, а также
вращаться вокруг своего центра. Количество возможных вращений зависит
от размерности куба. Исходя из этого, логично составить большой куб из
маленьких кубиков размерностью 1х1. Количество таких маленьких
кубиков в большом кубе равно размерности в третий степени. Каждый
маленький кубик состоит из шести плоскостей.
Построение куба производится путем клонирования модели (prefab’a)
маленького кубика. И каждому маленькому кубику присваиваются
собственные координаты, потом кубик становится дочерним объектом
большого куба. Получается множество маленьких кубиков, расстояние
13
между которыми равно 0. В итоге пользователь видит большой куб,
который можно вращать.
Для простоты вычислений в программе применяется другое
представление маленьких кубиков - это одномерный массив, содержащий
ссылки на всё объекты. Это облегчает доступ к объектам, а также
предоставляет боле удобный вид куба и его состояния на конкретный
момент времени.
Данный
функционал
описан
в
методе
CreateAtomCubes().
На рисунке 2.1 представлена игровая модель куба.
Рис. 2.1 - Игровая модель
14
GameToBegin()
и
2.1.2 Вращение куба вокруг своего центра
Необходимо вращать куб вокруг своего центра. Для простоты центр
куба всегда находится в центре глобальных координат (это задается при
построение куба). Кубик состоит из маленьких кубиков размерностью 1х1,
но так как они являются дочерними объектами, то изменение координат
большого куба влияет и на них. Т.е. когда мы получаем изменение вектора
вращения, мы начинаем вращать куб вокруг точки X(0,0,0) по вектору UP
или RIGHT зависимости от вектора вращения.
Данный
функционал
описан
в
методе
ProcessMovement()
и
FindInput().
2.1.3 Вращение слайсов
Необходимо вращать слайс по заданной оси. Так как слайс состоит из
набора маленьких кубиков размерностью 1х1, то непосредственно
необходимо перемещать именно их в пространстве.
Вращение происходит, когда пользователь водит пальцем по экрану
устройства, до этого, выбрав какой именно слайс он хочет вращать. Когда
был получен вектор вращения, слайс начинает вращаться вокруг точки
(0,0,0), по вектору RIGHT,UP или FORWARD.
Но
возникает
проблема,
если
пользователь
предварительно
перевернул весь куб и изменил направление осей. Возможно, что
направление движение пальца по экрану не будет соответствовать
направлению движения слайса. Поэтому необходимо переводить систему
координат экрана в глобальную систему координат сцены. Для этого
строим две точки. Первая точка: точка перед камерой в сцене, которая
соответствует начальным координатам пальца на экране. Вторая точка:
точка перед камерой в сцене, которая соответствует текущим координатам
пальца на экране. В итоге мы получаем вектор, переведенный из координат
15
экрана в глобальные координаты сцены. Теперь нам необходимо сделать
проекцию этого вектора на три основных вектора сцены, на вектор
RIGHT,UP и FORWARD. Мы получаем три числа, складываем их вместе и
это наше изменение угла при вращении слайса. На рисунке 2.2 показано
вращение слайса.
Рис. 2.2 - Вращение слайса
После проделанной процедуры только две стороны слайса вращаются
в
нужном
направлении,
остальные
стороны
вращаются
в
противоположном. Это происходит из-за того, что при вращении слайса
необходимо учитывать, с какой именно стороны мы начинаем вращать
слайс. Для полного соответствия движению пальца на экране и движению
16
слайса необходимо домножать вектор вращения на -1, чтобы вращать в
противоположном направлении. В каком именно случае это делать,
выбирается путем вычисления, к какому кубику мы обратились для
вращения.
После того как мы закончили вращать слайс, его необходимо
довернуть до правильного положения – когда углы наклона сторон слайса
совпадают с углами наклона сторонами куба. Это делается путем
вычисления ближайшего состояния и доворота слайса на необходимое
количество градусов.
После всех проделанных операций у нас имеется несоответствие
логического представления куба и его фактического состояния, поэтому
необходимо поменять местами кубики в массиве, так чтобы они
соответствовали фактическим позициям. Это делается путем изменения
индекса для кубиков, входивших в слайс. Данный функционал описан в
методе ProcessMovement() и FindInput().
2.2 Работа с текстурами
Так как это приложение является игрой, то очень много связано с
текстурами.
2.2.1 Термины и основные принципы
В среде разработке есть целый ряд понятий и связанных с ними
технологий, которые условно можно отнести к технологиям по работе с
текстурами. Все они прямо или косвенно направлены на отображении
текстур. К ним можно отнести:
⋅
Меш;
⋅
Материал;
⋅
Текстура;
17
⋅
Шейдер.
Меш – это координатная сетка, состоящая из треугольников. Она
задается массивом из треугольников, треугольник в свою очередь задается
смещением каждой вершины по материалу. В итоге при необходимости
можно получить нелинейное отображение текстуры. Меш бывает как
полигональный, так и состоящий из двух треугольников. В случае данного
приложения был использован стандартный меш, который создается при
создании объекта Plane.
Материал – это структура, которая содержит разнообразные
параметры по отображению текстуры. Такие как способ отображения,
уровень фильтрации, а также смещение и масштаб на текстуре. Материал и
меш в Unity3D существуют раздельно, так как меш может отвечать за
физику объекта. Материал может быть как общим, т.е. принадлежать сразу
нескольким объектам, так и частным.
Текстура – это массив цветов каждого пикселя. В Unity3D есть класс,
который представляет текстуру – это Texture2D. Он содержит набор полей
и методов для работы с текстурой непосредственно, такие как «изменить
пиксель» или «применить компрессию».
Шейдер - это подпрограмма по отрисовке текстуры. Обычно она
пишется на собственном языке. И концепция написания такова, что мы
задаем последовательность отрисовки и на каждом этапе применяем какиенибудь фильтры или алгоритмы. Шейдер может быть рассчитан на
несколько текстур. Все современные 3D приложения используют шейдеры
для создания реалистичных поверхностей и много другого. В случае с
iPhone шейдеры пишутся на специальном эмулирующем языке. В Unity3D
Шейдер как подпрограмма не может существовать без материала.
В Unity3D работа с текстурами специально упрощена и сделана
удобной.
Мы можем складывать необходимые изображения в папке
Resourses, а потом, когда программа запущена, по мере необходимости
подгружать их оттуда. Это делается одним методом с указанием
18
относительного пути до файла. При загрузке изображения мы создаем
экземпляр объекта Texture2D и присваиваем ему результат загрузки. И
можем свободно присоединять текстуры к материалу, для отображения на
сцене.
2.2.2 Загрузка текстур на грани куба
Так как у нас имеется много маленьких кубиков, из которых состоит
большой куб, то соответственно отображать текстуры необходимо на
гранях маленьких кубиков. Значит необходимо для каждого кубика делать
смещение у материала, а также изменять масштаб отрисовки текстуры, для
того чтобы отображать только часть изображения. Смещение и масштаб
зависят от размерности куба, а также от положения маленького кубика.
Также
от
положения
маленького
кубика
зависит,
какие
именно
изображения будут находиться на гранях. За смену изображений на гранях
отвечает метод ChangeTexture. Его вызов происходит, когда выставлен
соответствующий флаг. В нем перебираются все маленькие кубики и для
каждого считаются смещение, масштаб, а также выбирается, какая именно
текстура необходима на той или иной гране этого кубика. Вычисление и
выбор текстуры происходит не в данном методе, а в экземпляре класса
SideTexture . Данный объект содержит набор из 6 изображений на каждую
сторону куба, а также несколько вспомогательных текстур. Также объект
содержит конструктор, в который передается размерность куба, метод
установки текстур и два индексатора. Первый выдает текстуру на
определенную сторону, а второй возвращает объект класса atomTexture, в
котором как раз и содержится информация для каждого маленького кубика.
На рисунке 2.3 представлена смена текстур на гранях куба.
19
Рис. 2.3 – Смена текстур на гранях куба
2.2.3 Представление текстур в памяти. Класс ListTexture
Для удобной работы с текстурами был написан класс ListTexture. В
него
инкапсулирован
массив
текстур,
а
также
вспомогательные
переменные. В обязанности данного класса входит не только добавление и
хранение изображений доступных для нанесения на стороны кубика, а
также слежение за состоянием отображения этих изображений в меню
выбора. Так как в один момент времени пользователь может видеть только
6 изображений, то введено понятие “Окно” - это область видимости
изображений. У окна есть размер, начало и конец. И когда программа хочет
получить первое изображение из области видимости, то она обращается к
индексатору и получает необходимое изображение. Передвижение окна
видимости по списку изображений происходит путем Обращения к
методам Next и Last, также программа может узнать, возможно ли
продвижению по списку с помощью методов IsNext и IsLast.
20
2.2.4 Заполнение массива текстур
Для загрузки текстур из папки ресурсов или сервера используется два
статических метода FillCurtextureList и LoadImgFromSerever. Первый метод
необходим для начальной загрузки списка, второй для подгружения
дополнительного контента порциями. Метод сам определяет, откуда
необходимо грузить изображения и в каком количестве, а также
осуществляет контроль над ходом выполнения и в случае неудачи
оповещает пользователя об этом.
2.2.5 Шейдер и суммирование альфа слоя для выделения.
Так как стандартный материал не поддерживает многослойность
текстур на поверхностях игровых объектов, возникла необходимость в
написании пользовательского шейдера для реализации данной функции.
Данный
шейдер содержит две текстуры: главную текстуру и маску.
Главная текстура - это часть изображения, которое необходимо отрисовать
на грани маленького кубика, а маска - это рамочка выделения или
обрамления в зависимости от игрового состояния. Шейдер поэтапно
выполняет следующие действия:
⋅
выключает отображение альфа слоя при рисовании;
⋅
рисует главную текстуру;
⋅
включает отображение альфа слоя;
⋅
рисует маску.
2.3 Пользовательский графический интерфейс (GUI)
GUI является неотъемлемой частью всех современных приложений,
он должен быть удобным и понятным пользователю. Каждая среда
21
разработки имеет свои особенности работы с GUI и Unity3D не
исключение.
2.3.1 Основные принципы работы GUI в Unity3D
Unity3D – это инструмент для создания 3D сцен, но также с помощью
него можно рисовать и 2D графику. За отрисовку и события графического
интерфейса в моей программе отвечает скрипт myGUI. Он унаследован от
базового класса Unity3D MonoBehavior. В нем переопределены три метода
Start() Update() и OnGUI(). Для оптимизации скорости работы приложения
в Unity3D введено ограничение на использование методов отрисовки GUI,
оно заключается в том, что использование этих методов возможно только в
переопределенном методе OnGUI(). Благодаря этому ограничению,
программа
всегда
знает,
что
необходимо
отрисовать
и
может
оптимизировать данный процесс.
В
Unity3D
предусмотрен
набор
специальных
классов
для
отображения GUI, но так как была поставлена задача использовать
уникальный
инструментов
графический
интерфейс,
воспользоваться
не
то
полной
удалось.
мощностью
Первое
этих
ограничение
заключалось в том, что все кнопке GUI имеют свою уникальную текстуру,
а также должны по-разному отображаться при наведении на них мыши –
Hower эффект. Также область нажатия на некоторые кнопки не
соответствовала их рисуемым размерам. Таким образом, рисование GUI
свелось к построению машины состояний, и в каждом состоянии
задавалась отрисовка GUI. То есть программа многократно вызывала метод
OnGUI() класса myGUI и рисовала необходимые элементы GUI в
конкретном состоянии.
22
2.3.2 Машина состояний
Отображение
GUI
было
разделено
на
состояния,
которые
максимально точно отображали правильность поведения программы:
⋅
STATE_SPLASH;
⋅
STATE_SOUNDBEGIN;
⋅
STATE_PLAYSCENE;
⋅
STATE_SETTINGS;
⋅
STATE_THEMES;
⋅
STATE_THEMESPICKED;
⋅
STATE_SCORES;
⋅
STATE_ABOUT.
STATE_SPLASH – это начальное состояние игры, в котором
отображается картинка с логотипом игры. Оно продолжается 3.5 секунды
после полной загрузки приложения.
STATE_SOUNDBEGIN – Это экран включения или выключения
звука в игре, виден сразу после отображения логотипа игры.
STATE_PLAYSCENE
–
это
основное
состояние,
в
котором
непосредственно игрок может управлять кубом.
STATE_SETTINGS – это экран настроек приложения.
STATE_THEMES – экран выбора темы изображений, которые нужно
наложить на грани куба.
STATE_THEMESPICKED
–
экран
выбора
изображения
для
накладывания на грани.
STATE_SCORES – игровая статистика игроков.
STATE_ABOUT – экран информации о приложении.
Также помимо состояний существуют флаги, необходимые для
отображения специальных сообщений - Warnings.
23
На рисунке 2.4 представлено переключение между состояниями.
Рис. 2.4 - Переключение между состояниями
2.3.3 Отображение кнопок и меню
Отображение кнопок происходит в два этапа. Сначала выбирается
необходимая текстура для рисования, потом отмечается активная область
кнопки.
За выбор текстуры отвечает метод OnHower() класса myGUI. В него
передаются координаты места, где необходимо нарисовать кнопку, и две
текстуры: первая рисуется, если мышь не наведена на кнопку, вторая
рисуется в противоположном случае. Метод OnHower() берет место
положения мыши и проверяет, не попадает ли данная координата в
прямоугольник рисования. Этот прямоугольник задается координатами
верхнего угла и размера сторон.
24
На втором этапе мы с помощью стандартного метода Unity3D рисуем
кнопку. При этом вместо текстуры мы передаем пустое значение - null.
Данный метод возвращает после выполнения логическое значение. Если
возвратилось true, то значит, в последнем кадре отрисовки произошло
нажатие на данную кнопку, и соответственно выполняются необходимые
действия. Таким образом, можно получить разные значения активной
области и области отображения кнопки.
2.3.4 Окно выбора текстур
Данное окно отображается в состоянии STATE_THEMESPICKED. На
нем можно просмотреть доступные изображения для наложения на грани
куба, а также выполнить удаление или наложение изображения. На рисунке
2.5 представлено окно выбора текстур.
25
.
Рис. 2.5 - Окно выбора текстур
С данным элементом тесно связан объект ListTexture, так как именно
из него берутся необходимые изображения. Ввиду того, что ListTexture сам
управляет окном видимости, то GUI просто использует методы и
индексаторы данного класса. Для отображения в ячейке происходит
обращение к индексатору класса ListTexture и возвращается необходимая
текстура для данного слота. При навигации по изображениям вызываются
методы Next() и Last(). С помощью них передвигается окно видимости,
причем
все
проверки
на
корректность
передвижения
окна
инкапсулированы в классе ListTexture. Так же в правой части экрана
имеется символьное отображение сторон куба, и для каждой стороны
отображается маленькая картинка, соответствующая изображению на
26
данной стороне куба. Для того чтобы нанести картинку на сторону куба,
необходимо
выбрать
данную
сторону
и
нажать
на
необходимое
изображение.
На рисунке 2.6 представлена навигация между изображениями.
myGUI
ListTexture
Next()
Рис. 2.6 - Навигация между изображениями
На рисунке 2.7 изображено последовательность отрисовки текстуры.
Рис. 2.7 - Рисование текстуры
2.4 Звук
27
Ни одна современная игра не обходится без музыкального
сопровождения и всевозможных звуковых эффектов. Так и при создании
моего приложения, была необходимость использовать звук.
2.4.1 Принцип и особенности работы со звуком в Unity3D
Работа со звуком в Unity3D также относительно проста, хотя
возможности весьма велики. Можно накладывать фильтры, закреплять
звуковые эффекты за объектами, в результате чего громкость и
стереоэффект регулируется автоматически. Для того чтобы закрепить за
объектом звук, необходимо создать и присоединить к объекту экземпляр
класса AudioSource, а потом, обращаясь к методам, добавлять к
проигрыванию необходимые ресурсы.
2.4.2 Работа со звуком. Класс SoundManager
Для удобного и быстрого проигрывания создан класс SoundManager и
нумератор Sound. В Sound храниться соответствие между звуками и их
представлением.
При
создании
экземпляра
класса
SoundManager
передается AudioSource, который в последствии будет использоваться для
проигрывания звуков. В SoundManager реализованы методы Play(), Stop(),
Pause() (проигрывание, остановка проигрывания, а также пауза), которые
фактически являются оберткой для методов класса AudioSource. Для
проигрывания звука необходимо указать SoundManager'у где и какой звук
проиграть. На рисунке 2.8 изображена связь между объектами и классом
SoundManager.
28
myGUI
-_sounManager
1
1
CubeScript
-_soundManager
SoundManager
1
-AudioSource
-AudioClip
+Play ()
+Play(ввод Sound )
+Stop ()
+Pause()
1
Рис. 2.8 - Связь между объектами и классом SoundManager
В игре существуют два вида звуков. Первый – это мгновенные звуки,
которые звучат, когда происходит нажатие на активные элементы меню
или нажатие на куб и т.д. Второй тип это фоновая музыка – звук, который
необходимо проигрывать пока приложение запущенно, но так как время
работы приложения может быть велико, нецелесообразно делать файл
большого размера, гораздо проще повторно запускать фоновый звук. Также
если пользователь захочет выключить звук во время игры, необходимо
поставить на паузу фоновый звук. Поэтому метод Play() класса
SoundManager перегружен. И для каждого типа используется свой метод.
2.5
Фотографирование
и
использование
пользовательских
изображений
Так как количество изображений, которые можно установить вместе
с приложением ограничено, то необходимо было сделать способ
пользователю добавлять собственные наборы изображений. Одним из
таких способов является использование изображение из личной галереи
или фотографирование на камеру.
29
2.5.1 Использование нативного кода в Unity3D
Использовать сторонние библиотеки напрямую из Unity3D basic
запрещено. Поэтому необходимо было придумать способ использования
их. Результатом сборки проекта на Unity3D является проект на XCode’е.
Таким образом, если мы внесем изменения в этот проект, то сможем
использовать нативный код, но, к сожалению, не напрямую. В данном
приложении был создан специальный класс NativeDispatcher. Он отвечает
за использование фотокамеры и стандартного диалога выбора файла. Этот
класс является реализацией системного интерфейса, поэтому необходимо
было просто переопределить методы и добавить импорт заголовочного
файла в стандартный контролер приложения, который был создан в
Unity3D.
Вызов диалога фотографирования или выбора файла выглядит
следующим образом. При нажатии на соответствующую кнопку GUI
происходил вызов метода класса PhotoScript WaitPhoto() или WaitFolder()
соответственно. Данные методы говорят программе, что необходимо
вызвать диалог. Программа на Unity3D записывает в специальный
настроечный файл необходимую строку и начинает ждать ответа от класса
NativeDispatcher. В свою очередь, данный класс просматривает этот
настроечный файл и, находя в нем нужную строку, выполняет вызов
диалога. После того как диалог завершится, NativeDispatcher выполняет
запись
в
настроечный
файл
строки,
которая
содержит
путь
до
необходимого изображения, и программа на Unity3D закачивает это
изображение.
2.5.2 Принцип работы класса PhotoScript
После того как был вызван метод WaitPhoto() или метод WaitFolder(),
происходит задержка в одну десятую секунды, это необходимо, для того
30
чтобы приложение успело показать надпись “Loading”. После этого
выставляется
соответствующий
флаг,
и
метод
Update(),
который
выполнятся каждый кадр, делает запись в настроечный файл. При этом
необходимо убедиться, что этот файл пуст, иначе программа может начать
работать некорректно, так как некоторые методы могут также использовать
данный файл. После записи начинается ожидание, т.е. программа на
Unity3D просматривает данный файл на предмет ответа NativeDispatcher.
Но так как, когда вызывается диалог фотографирования или выбора файла,
управление от программы на Unity3D переходит к Операционной системе,
и программа на Unity3D засыпает - приостанавливает свою деятельность до
получения управления. После того как управление передано обратно,
программа на Unity3D считывает строку из настроечного файла и удаляет
её – это делается, потому что необходимо очистить настроечный файл
после
его
использования.
Далее
проверяется
результат
работы
NativeDispatcher, так как диалог мог быть отменен. Если диалог не отменен,
то
путь
до
изображения
передаётся
методу
GetPhoto(),
который
непосредственно закачивает с диска изображение в программу. После
загрузки изображения происходит сдвиг окна видимых изображений до
конца, и фотография добавляется в конец этого списка, после чего исчезает
надпись “Loading”.
2.5.3 Принцип работы нативного класса
NativeDispatcher
сканирует
настроечный
файл
на
предмет
необходимости вызова диалога. Если соответствующая строка найдена, то
он выполняет вызов диалога, предварительно удалив строку запроса из
настроечного файла. Когда диалог закончен, то в зависимости от
результата выполняются следующие действия. Если диалог отменен, то в
настроечный файл заносится строка “Cancel”. Если диалог успешен, то
изображение сохраняется на диск, предварительно уменьшаясь до размеров
31
256х256 пикселей, для того чтобы не занимать много места в оперативной
памяти. После сохранения файла происходит запись в настроечный файл
строки с путем до этого файла и продолжается ожидание.
2.6 Игровая статистика
Для отслеживания результатов игры, а также для внесения
соревновательного фактора в игру, создан модуль статистки.
2.6.1 Правила победы и подсчета игровой статистики
Победителем
считается
тот
игрок,
который
смог
после
перемешивания куба вернуть его в исходное состояние. При победе
запоминается количество ходов на момент победы и время, которое
потребовалось для того, чтобы собрать куб. Запоминаются все результаты,
однако выводятся только первые 10. Это сделано для возможного
расширения игровой статистики.
2.6.2 Окно игровой статистики с его особенностью
Окно игровой статистики доступно в состоянии STATE_STAT. Оно
отображает 10 лучших результатов, также в нем есть возможность
отсортировать результаты по времени или ходам. Причем наборы этих
сортировок могут различаться ввиду того, что хранятся все результаты
побед. Сортировка производится методом QUICK SORT. Также это окно
доступно после победы, и при этом, если ваш результат попал в 10 лучших,
он подсветится оранжевым цветом.
32
2.6.3 Сохранение и загрузка игровой статистики
Сохранение
игровой статистики производится путем добавления
соответствующих строк в .txt файл, который находится в домашней
директории приложения. Ввиду того, что приложению разрешено писать на
локальный диск только в домашнюю директорию, то писать приходится
именно туда.
Загрузка производится каждый раз, когда необходимо отобразить
окно статистики. Загружаются все строки из файла статистики, далее
происходит необходимая сортировка этих строк. На отображение выдаются
первые 10 строк статистики.
2.7 Использование Интернета для загрузки изображений
Еще одним из способов пополнения галереи изображений является
использование Интернет.
2.7.1 Принципы работы с Интернетом в Unity3D
Работа с сетью в Untity3D в основном производится посредством
пост-запросов. В среде разработки есть очень удобное средство для
общения с серверами и базами данных - класс WWW. Он умеет по
заданному заранее шаблону опрашивать сервер и получать необходимую
информацию. Но так как мы говорим о 3D - игре, то пользователь должен
постоянно иметь отклик GUI, поэтому все запросы должны происходит в
отдельном потоке выполнения. Для этого в Untity3D предусмотрена
возможность запуска подпрограмм, которые выполняются параллельно и
при этом используют то же адресное пространство, т.е. имеют доступ к тем
33
же переменным. При работе с Интернетом работа приложения выглядит
следующим образом: мы составляем запрос к серверу и начинаем
выполнение запроса в подпрограмме. Подпрограмма ожидает, пока
выполнится подзапрос, при этом основная программа не повисает, и мы
можем таким образом подгружать информацию порциями и предоставлять
возможность манипулировать ей пользователю.
2.7.2 Описание ресурса Panoramio
Panaramio
возможность
–
это
получения
Интернет
сервис,
фотографий
который
окрестностей
предоставляет
по
заданным
координатам. Данный ресурс обладает огромной базой фотографий, все
они прикреплены к конкретному месту на карте мира. Добавить
фотографии на сайт может любой пользователь. Просмотр фотографий
возможен как на веб-сайте, с помощью специального флеш элемента, так и
с помощью запросов к серверу из любого приложения, которое имеет
доступ в Интернет. Так как iPhone имеет GPS модем, то использование
Panaramio становится крайне заманчивым – гораздо интересней собирать
куб, на котором нанесены достопримечательности того места, где вы
находитесь. К тому же можно использовать данное приложение не по
прямому назначению, а ещё и как навигатор или гид по окрестностям и
просматривать фотографии.
2.7.2.1 API panoramio
Сервер
воспользоваться
Panоramio
услугами
предоставляет
данного
ресурса.
любому
Сделать
возможность
это
можно
посредством общедоступного API, который размещен у них на сайте в
разделе Suport.
34
Cервер составляет JSON объект и отправляет приложению обратно. В
данном
ответе содержится информация об изображениях: широта и
долгота на местности, название, размер, автор, и непосредственно ссылка
на само изображение. Т.е. мы имеем возможность загрузить необходимое
подмножество изображений из множества, которое содержал ответ сервера.
2.7.2.2 Формат JSON
JSON (англ. JavaScript Object Notation) – это текстовый формат
обмена данными, основанный на JavaScript и обычно используемый именно
с этим языком. Как и многие другие текстовые форматы, JSON легко
читается людьми.
Несмотря на происхождение от JavaScript (точнее, от подмножества
языка
стандарта
ECMA-262
1999
года),
формат
считается
языконезависимым и может использоваться практически с любым языком
программирования. Для многих языков существует готовый код для
создания и обработки данных в формате JSON.
Практическая
польза
использования
JSON
открывается
при
использовании технологии AJAX. Формат JSON является более кратким и
удобочитаемым по сравнению с XML, является подмножеством синтаксиса
языка Javascript и преобразуется в структуру данных встроенной в него
функцией eval(). Кроме того, в JSON-код возможна вставка вполне
работоспособных функций.
JSON строится на двух структурах:
Набор пар имя/значение. В различных языках это реализовано как
объект, запись, структура, словарь, хэш-таблица, список с ключом или
ассоциативный массив.
Пронумерованный
набор
значений.
Во
многих
языках
это
реализовано как массив, вектор, список или последовательность и является
универсальными структурами данных. Теоретически, все современные
35
языки программирования поддерживают их в той или другой форме. Так
как JSON используется для обмена данными между различными языками
программирования, то имеет смысл строить его на этих структурах.
В JSON используются их следующие формы:
Объект - неупорядоченное множество пар имя/значение, заключённое
в фигурные скобки { }. Между именем и значением стоит символ «:», а
пары имя/значение разделяются запятыми.
Массив (одномерный) - множество значений, имеющих порядковые
номера (индексы). Массив заключается в квадратные скобки
[ ]. Значения
отделяются запятыми.
Значение может быть строкой в двойных кавычках, числом, true,
false, null, объектом или массивом. Эти структуры могут быть вложены
друг в друга.
Строка — это упорядоченное множество из нуля или более символов
юникода, заключенное в двойные кавычки, с использованием escapeпоследовательностей, начинающихся с обратной косой черты (backslash).
Символы представляются простой строкой.
Строка очень похожа на строку в языках С и Java. Число тоже очень
похоже на С или Java-число, за исключением того, что восьмеричные и
шестнадцатеричные форматы не используются. Пробелы могут быть
вставлены между любыми двумя символами.
2.7.2.3 Принцип работы скрипта PanoramioRequest
Данный скрипт состоит из трех основных частей: получения
координат местонахождения, запроса к серверу с целью получения
множества ссылок на фотографии и загрузки самих фотографий.
Когда
пользователь
выбирает
категорию
LocalCalor,
то
запрашиваются координаты у спутника, потом посылается запрос серверу
на получение множества фотографий, причем, так как ответ сервера может
36
состоять только из 100 изображений, то необходимо сделать этот запрос
несколько раз, уточняя площадь местности. Если фотографий пришло
мало, то необходимо увеличить площадь, если их пришло 100, то мы не
можем точно сказать сколько их, и поэтому необходимо уменьшить
площадь, чтобы более точно передать фотографии на местности. После
того как необходимый набор получен, он сортируется по месту
нахождения: от самого близкого, до самого дальнего от пользователя.
Загрузка фотографий сделана по 8 штук, чтобы пользователь не
ожидал слишком долго. При этом пока идет загрузка изображений
пользователю
манипулировать
показывается
приложением:
надпись
“Loading…”
например
отменить
и
он
загрузку.
может
Если
загруженных фотографий пользователю не хватило, то он может загрузить
ещё 8. Данный алгоритм наглядно представлен на рисунке 2.9.
Рис 2.9. – Алгоритм Работы PanoramioRequest
Для того чтобы обеспечить работоспособность приложения, введены
два события:
⋅
невозможность подключения к wi-fi.
37
⋅
принудительное завершение запроса, если время на любое
действие превышает 30 секунд.
2.7.3 Загрузка изображений с сервера VitaSW
Еще
одним
средством
по
увеличению
набора
возможных
используемых изображений является получение изображений с сервера
VitaSW. На данном сервере находятся изображения, разделенные по
категориям.
2.7.3.1 Принцип работы скрипта VitaServerRequest
Обращение к серверу введется посредством http протокола. Сначала,
как и в обращении к серверу Ponaramio, получается набор ссылок на
изображения, а потом происходит скачивание изображений порциями по 4
штуки. Список ссылок на изображения хранится в текстовом файле на
сервере, поэтому происходит обращение именно к нему. Список со
временем
может
меняться.
Также
предусмотрены
принудительные
завершения запросов в результате недоступности wi-fi или превышения
лимита времени.
2.8 Сохранение и загрузка сцены
Так как на iPhone нет возможности работы одновременно нескольких
приложений, то при запуске приложения необходимо закрыть другое.
Также
возможно,
что
пользователю
позвонят
во
время
игры
и
операционная система устройства принудительно закроет приложение. Или
пользователь захочет отвлечься от игры, при этом, желая сохранить
текущее состояние. Поэтому необходимо было реализовать сохранение
игры.
38
2.8.1 Принципы сохранения объектов
Так как игровые объекты это не только поля с информацией, а также
большое количество ссылочных полей, то сохранить их при помощи
стандартных методов нельзя. Пришлось писать самостоятельно класс по
сохранению нужных полей объектов. При этом происходит сохранение в
двоичные файлы флагов состояния, ходов и изображений.
2.8.2 Принцип работы скрипта StartScript
Данный класс унаследован от системного класса MonoBehaviour и
реализует
три
метода
родительского
класса:
Start(),
Update()
и
OnApplicationQuit().
2.8.3 Сохранение
Сохранение происходит в несколько этапов:
1. Сначала сохраняются изображения, которые наложены на грани
куба. Но так как сохранение текстуры стандартными методами возможно
только если текстура подходящего формата, то если сохранение
невозможно, сохраняется только название темы и номер изображения.
2. После того как текстуры на гранях сохранены, происходит
сохранение игровых настроек: размерности куба, времени и количества
ходов, потраченных игроком, а также положение в пространстве и угол
поворота куба.
3. После этого происходит сохранение состояния куба, то есть
расположение маленьких кубиков.
4. Происходит сохранение состояния GUI.
39
Перед сохранением делается проверка на то, что все слайсы
довернуты, если слайс находится в движении, то он доворачивается, и
начинается процесс сохранения.
2.8.4 Загрузка
Загрузка также происходит в несколько этапов:
1. Загрузка состояния игры;
2. Загрузка текстур на поверхности куба;
3. Загрузка состояния GUI;
4. Загрузка состояния куба.
При этом если какой-то файл не найден, то происходит загрузка
стандартных параметров и текстур.
40
3 Улучшение производительности и устойчивости программы
Ввиду того, что iPhone имеет ограничение по производительности
центрального процессора, объема оперативной памяти и т.д., написанная
программа работала крайне нестабильно и очень медленно. Поэтому
пришлось внести ряд значительных изменений в логику программы.
Изменения были внесены в модель куба, работу с текстурами и их
отрисовку, в способ хранения текстур в памяти.
3.1 Характеристики iPhone
Мобильные устройства от Apple делятся на несколько видов.
Программа Cube-Rube поддерживает несколько из них: iPhone, iPhone3G,
iPhone3GS, iPod touch 2G. Ниже перечислены основные характеристики
этих устройств[5],[6],[7].
iPhone:
модель - A1203 :: MA712LL/A (8 GB), A1203 :: MA384LL/A (16 GB)
Процессор - Samsung S3C6400 ARM 620 МГц Частота программно
ограничена до 412 МГц, PowerVR MBX-Lite graphics.
Память - 64 MB RAM; 4, 8 и 16 Гб Flash
Камера – 2 мегапикселя, программная реализация записи видео.
iPhone 3G:
модель - A1241
Процессор - Samsung S3C6400 ARM 620 МГц Частота программно
ограничена до 412 МГц, PowerVR MBX-Lite graphics
Память - 128 MB RAM; 4, 8 и 16 Гб Flash
Камера - 2 мегапикселя, программная реализация записи видео
iPhone 3GS:
41
модель - A1303
Процессор - Samsung S5PC100 ARM 833 МГц, PowerVR SGX
graphics
Память - 256 MB RAM; 16 и 32 Гб Flash
Камера - 3 мегапикселя, автофокус, запись видео VGA
iPod touch 2G
модель – A0903
Процессор - Samsung S3C6400 ARM 620 МГц Частота программно
ограничена до 412 МГц, PowerVR MBX-Lite graphics
Память - 128 MB RAM; 4, 8 и 16 Гб Flash
Камера – отсутствует.
Все устройства имеют экран 320х480 пикселей, у всех устройств
управление производится пальцем, который нажимает на сенсорную
панель. Из данных сведений видно, что мобильные устройства весьма
сильно уступают в производительности персональному компьютеру, а
требования, которые применяются к приложениям, не уступают в
требованиях к приложениям на персональных компьютерах. Поэтому
необходимо применять соответствующие техники программирования и
проектирования приложений.
42
3.2 Проблема производительности
После того как программа была спроектирована и написана, она
прошла тестирование, и выяснилось, что при размерности куба 2х2 FPS
равняется 14, а при максимальной 6х6 FPS падало до 0-1, тогда как для
нормальной работы на устройстве требуется минимум 14-16 FPS. Стало
ясно, что необходимо найти узкие места и устранить их. Как оказалось,
первым проблемным местом была элементарная часть куба – плоскость, а
вторым особенность графического ядра iPhone по отображению текстур. В
итоге описанных ниже мер не хватило, и решено было, что максимальная
размерность куба будет не 6, а 5.
3.2.1.Уменьшение количества полигонов
В состав этой элементарной части куба – плоскости, входил Меш,
количество полигонов которого равнялось 450. Соответственно, что при
размерности 2х2, количество полигонов было равно:
8кубиков * 6 плоскостей * 450 полигонов = 21600.
А когда размерность куба возрастала до 6, то количество полигонов
было равно:
6*6*6 кубиков * 6 плоскостей * 450 полигонов = 583 200.
Такое большое количество полигонов, конечно, не могло работать на
мобильном устройстве. Но с помощью Unity3D невозможно создать
плоскость с меньшим количеством полигонов, поэтому пришлось делать
Меш отдельно в программе 3DMax. С помощью данного редактора был
создан Меш, содержащий всего 2 треугольника, что многократно
уменьшило количество полигонов необходимых для рисования модели.
Данное
вмешательство
позволило
увеличить
количество
FPS
при
максимальной размерности куба до 5. Также все маленькие кубики,
которые не видны пользователю, т.е. те кубики, которые находятся внутри
43
куба, не рисовались. Что позволило дополнительно снизить количество
полигонов.
3.2.2 Модернизация поворота куба
Отличительной
перемещении
особенностью
большого
количества
Unity3D
является
объектов
все
то,
что
объекты
при
сцены
перерисовываются многократно. Поэтому при повороте куба вокруг своей
оси производительность падала в 2-3 раза. Было решено вращать не куб, а
камеру вокруг него. Был добавлен скрипт RotateObjectScript, который
управляет передвижением камеры вокруг куба. Если было произведено
событие нажатия мыши, то скрипт начинал работать и поворачивать
камеру вокруг куба. При этом производился пересчет координат экрана
устройства в координаты сцены, для того чтобы направление движения
камеры совпадало с направлением движения пальца. После внесения этого
изменения
объектам
не
было
нужды
перерисовываться,
и
производительность при движении перестала ухудшаться.
3.2.3.Уменьшение количества DrawCalls
DrawCalls – это количество вызовов рисования материалов. На
рисование одного материала тратится один вызов, даже если материал
используется многократно. Отличительной особенностью графического
ядра iPhone является то, что при увеличении DrawCalls резко падает
производительность, поэтому необходимо было свести DrawCalls до
минимума. До внесения изменения в программу каждой поверхности
маленького кубика, соответствовал собственный материал. И в итоге
получалось, что DrawCalls росло в геометрической прогрессии при
увеличении размерности. При размерности 2 DrawCalls было равно:
8 кубиков * 6 поверхностей * 1 материал = 48
44
А при размерности 6 DrawCalls уже было:
6 * 6 * 6 кубиков * 6 * 1 = 1296
Однако приложение на iPhone может работать нормально с
DrawCalls, не превышающего 100.
После
выявления
данной
проблемы
количество
материалов
используемых на кубе уменьшилось до 7 при любой размерности. По
одному на каждую сторону и один на внутренние кубики. Данные меры
помогли увеличить производительность на размерности 6х6 до 10 FPS.
3.3 Проблема нехватки оперативной памяти
Количество оперативной памяти, которое отводится под любое
приложение на iPhone, не должно превышать 50 мб. Если программа
попытается использовать больше оперативной памяти, то операционная
система устройства принудительно закроет приложение, и в лог запишется
ошибка недостатка памяти.
В нашем случае возникла проблема при скачивании фотографий с
Интернета, а также при фотографировании. Данная проблема возникла изза того, что алгоритм сжатия текстур работает только с квадратными
текстурами, размерность которых ровна степени 2. Плюс iPhone не
позволяет сжимать текстуры во время работы приложения. За него это
необходимо сделать ещё на этапе компиляции приложения. Поэтому все
изображения, которые скачивались из Интернета или получались при
помощи фотографирования, были несжатыми, а на хранение несжатой
текстуры в оперативной памяти требуется 4 байта на каждый пиксель
текстуры. К тому же iPhone не поддерживает технологий свопинга.
Поэтому возникла необходимость в реализации некоторого подобия
свопинга.
45
3.3.1 Реализация механизма свопинга
Свопинг - Один из механизмов реализации виртуальной памяти, при
котором
отдельные
запущенные
процессы
(обычно
неактивные)
перемещаются из ОЗУ на жёсткий диск, освобождая ОЗУ для загрузки
других процессов. Основное отличие этого механизма от страничного
заключается в том, что процессы перемещаются между ОЗУ и жестким
диском целиком, поэтому иногда некоторые процессы могут полностью
отсутствовать в ОЗУ.
Рис 3.10. – Диаграмма Механизма свопинга
46
Реализация данного механизма построена на базе класса ListTexture,
и её наглядно можно увидеть на рисунке 3.10. Для хранения текстур в этом
классе использовался список объектов ArrayList. Данный ссылочный
список был заменен на написанный самостоятельно класс PagedList.
PagedList поддерживает все необходимые методы ArrayList, поэтому не
пришлось переписывать класс ListTexture. PagedList содержит массив
объектов PagedNode, данный класс является абстрактным[7],[8] и содержит
4 поля:
⋅
_container – непосредственно объект класса Texture2D.
⋅
Path – путь до файла на диске.
⋅
isPaged – флаг, который сообщает, если изображение сохранено
на диск.
⋅
isCritical – флаг, который говорит о том, что текстуру нельзя
сохранять на диск.
Также PagedNode содержит несколько конструкторов для удобства
работы с ним и 2 публичных свойства IsCritical - для доступа к полю
isCritical и Container. Container содержит в себе проверку на то, что если
текстура сохранена на диск, то необходимо её загрузить перед тем как
передать ссылку на поле _container, которое до загрузки равно null.
PagedNode содержит три абстрактных метода:
⋅
LoadContent()
⋅
SaveContent()
⋅
Destroy()
Это сделано для того, чтобы можно было выгружать любые объекты
на диск. Необходимо только изменить способ сохранения и загрузки
объекта.
Конкретной реализацией для текстур является класс PagedImgNode. В
нем реализовано сохранение и загрузка текстуры, а также уничтожение
текстуры.
Сам процесс свопинга сводится к следующему:
47
1)
Происходит добавление текстуры в объект ListTexture, при этом
если надо, объект помечается критическим.
2)
Происходит добавление объекта PagedImgNode в объекта класса
PagedList, при этом объекту отдается приказ сохраниться на диск. И
текстура принудительно удаляется из оперативной памяти. При следующем
обращении к объекту PagedImgNode происходит загрузка объекта в
оперативную память и
как только он становится не нужен, он опять
отправляется на диск. При этом так как объект уже сохранен на диск, то
непосредственно
сохранения
не
происходит,
происходит
только
выставление флага isPaged и удаление текстуры из оперативной памяти.
Так происходит потому что преобразование текстуры в двоичный формат
весьма
трудоемкая
операция,
которую
проводить
несколько
раз
накладно[10].
В результате ввода этого механизма целый ряд процессов претерпел
модернизацию, такие как: навигация по списку изображение в Окне выбора
текстур (Рис. 3.11.), отображение Текстур в Окне выбора текстур (Рис. 3.12,
3.13), скачивание из Интернета, и т.д.
Рис. 3.11 – Навигация в Окне выбора текстур
48
Рис 3.12 - Отображение текстуры в окне выбора текстур (без
загрузки)
Рис 3.13 - Отображение текстуры в окне выбора текстур (с загрузкой)
49
3.3.2 Модернизация алгоритма фотографирования
При фотографировании приложение также работало нестабильно и
иногда прекращало свою работу с ошибкой нехватки памяти. Это
возникало по причине того, что
разрешение фотоаппарата iPhone
1600*1200 пикселей и соответственно данная фотография занимала в
оперативной памяти 8 мб, а положить в оперативную память для
последующей обработки было необходимо. Мы могли уменьшить размер
изображения
только
после.
Поэтому
увеличивалось
использование
оперативной памяти при фотографировании на 8 мб. Для того чтобы
решить данную проблему, было решено на время вызова диалога
фотографирования выгружать из оперативной памяти текстуры GUI. А
потом, когда уже фотография имеет маленький размер, загружать текстуры
обратно, при этом время на выгрузку и загрузку маскировалось медленной
работы фотоаппарата iPhone.
50
Заключение
В
результате
проделанной
работы,
мной
спроектирована
и
реализована 3D - игра “Cube-Rube”. Получены большие знания в области
разработке iPhone приложений: работа с Интернетом, работа с памятью
мобильных устройств, оптимизация производительности. Также мной была
изучена среда разработке Unity3D: возможности редактора движка, слабые
и сильные стороны этого движка. Получен большой опыт разработки 3D
сцен: изучены основные понятия, изучен язык написания шейдеров,
изучена и понята работа с текстурами как в 3D, так и в 2D. Приобретен
опыт программирования на языке Objective – C и JavaScript. Более детально
изучена библиотека .NET, особенно её ранние версии. Изучена и
проанализирована библиотека Unity3D, составлены собственные классы,
которые
её
дополняют.
Изучен
механизм
свопинга.
Приложение
зарегистрировано на официальном сайте фирмы Apple AppStore и доступно
в свободной продаже под названием “Super Cube”.
51
Список используемых источников
1.
Официальная документация по Unity3D [Электронный ресурс] -
URL: http://unity3d.com/support/documentation (дата обращения: 06.04.2010).
2.
Официальное
[Электронный ресурс]
сообщество
разработчиков
на
Unity3D
-URL: http://unity3d.com/support/community (дата
обращения: 26.04.2010).
3.
Русское сообщество разработчиков на Unity3D [Электронный
ресурс] - URL: http://forum.unity3d.com (дата обращения: 06.04.2010).
4.
Unity3D
Типовые примеры и решения при разработке приложений на
[Электронный
ресурс]
-
URL:
http://blogs.unity3d.ru
(дата
обращения: 01.05.2010).
5.
Справочная информация по устройству фирмы Apple - Apple
iPhone [Электронный ресурс] - URL: http://www.apple.com/support/iphone
(дата обращения: 11.05.2010).
6.
Справочная информация по устройству фирмы Apple - Apple
iPod touch [Электронный ресурс] - URL: http://www.apple.com/support/ipod
(дата обращения: 26.05.2010).
7.
Официальная документация по Unity iPhone [Электронный
ресурс] URL: http://unity3d.com/unity/features/iphone-publishing.html (дата
обращения: 12.04.2010).
8.
Троелсен Э. С# и платформа .NET. - СПб.:Питер, 2004. - 796 c.-
(Библеотека программиста).
9.
Орлов С.А. Технология разработки программного обеспечения -
Питер,2003.-464c.-(Учебник для ВУЗов).
10. Энди Кармайкл, Дэн Хейвуд. Быстрая и качественная разработка
программного обеспечения.-Вильямс,2003.-400 с.
52
Download