Практический опыт переноса ресурсов из Flash в Unity 3D

в 8:40, , рубрики: flash, game development, iOS, unity3d, игры, разработка под iOS, метки: , , ,

Практический опыт переноса ресурсов из Flash в Unity 3D Буквально недавно мы с товарищами запустили наш первый проект под iOS — игрушку про змейку Shadow Snake. Хотелось опробовать разработку под iPad, поэтому решили перенести уже готовый проект, сделанный на Flash, тем более, что механика позволила очень гармонично использовать возможности сенсорного управления.

Конечно, первой идеей было попробовать AIR SDK — проект запустился, но из динамичной аркады он превратился в аркаду “походовую”. FPS был ужасно низким отчасти из-за того, что практически вся графика во флешке была векторной, а мобильный AIR с ней не очень дружит. Поэтому было решено использовать Unity 3D.

Unity 3D на тот момент уже хорошо зарекомендовала себя в мобильных играх и имела хорошую визуальную среду для создания игровых сцен. Благодаря этому можно было разделить непосредственно программирование, подготовку ресурсов и дизайн игровых уровней и распределить эти задачи по разным членам команды. Кроме того, по роду основной деятельности я давно уже работаю с C#, поэтому с Unity я чувствовал себя комфортно.

Встала задача, как перенести графику и анимации (в том числе составные) в новый проект.

Экспорт графики из Flash

Как открыть SWF и преобразовать векторные изображения в PNG или JPEG? Правильно! Нужно использовать Flash. А как сохранить полученные результаты на диск? Правильно! Нужно использовать AIR.

Растеризация была осуществлена при помощи BitmapData и PNGEncoder с последующим сохранением в файл при помощи FileStream.

Необходимо было выстроить процесс таким образом, чтобы анимации экспортировались с наименьшими “телодвижениями”. А именно, чтобы все метаданные (названия анимаций, раскадровка, масштаб кадров, параметры зацикливания) можно было редактировать в самой среде Flash.

Adobe Flash не позволяет добавлять к MovieClip дополнительную информацию, поэтому пришлось ввести несколько соглашений. Например, имена клипов, которые нужно было экспортировать, начинались с префикса “e_”. Этот префикс отрезался при формировании итоговых файлов. Для разметки анимации и задания ее свойств использовались метки кадров, заданные в определенном формате. В результате получился достаточно удобный синтаксис, а структура каждого экспортируемого MovieClip выглядела следующим образом:
Практический опыт переноса ресурсов из Flash в Unity 3D

На выходе приложения получался набор спрайтлистов и их описание в формате XML. Кому интересно, могут покопаться в исходниках. Исходники неподготовленные, недокументированные, as is :). Просто некогда сейчас оформлять их в “продукт”, но их можно растащить “на запчасти”.

Отдельно отмечу, что перелистывание кадров при растеризации в загруженном извне MovieClip требует “специфических” приемов. Это связано с поведением вложенных клипов — они могут появляться на несколько кадров, потом исчезать в процессе анимации. Поэтому для каждого нового прохода лучше создавать объект заново. Для получения списка доступных клипов в загруженном файле использовалась библиотека SWFExplorer.

Импорт графики в Unity 3D

После того, как ресурсы преобразованы в нормальный для обработки вид, спрайтлисты с их метаданными необходимо представить в понятном для Unity формате.

Мы решили не использовать готовые 2D-фреймворки под Unity, т.к. предполагалось обкатать технологию, получить новый опыт и лучше понять, как делать игры в терминах этой среды. Поэтому были придуманы 2 специальных компонента — AnimatedSprite и SpriteSheet.

Первый отвечал за собственно вывод спрайта в игровое пространство. Он создавал стандартные для Unity компоненты MeshFilter и MeshRenderer и наполнял их данными из SpriteSheet. Таким образом удалось использовать вкусные фичи, а ля Dynamic Batching.
Практический опыт переноса ресурсов из Flash в Unity 3D

SpriteSheet же содержал ссылку на подключаемую текстуру, список анимаций, кадров и другие настроки — всю ту информацию, которая выгружалась из SWF. Было решено хранить ее именно средствами Unity, чтобы иметь возможность корректировать параметры инструментами среды. SpriteSheet’ы генерировались автоматически в виде готовых префабов, которые затем размещались на сцене.

Результат работы AIR-конвертера состоял из png- и xml-файлов, поэтому на тот момент удобнее всего было разместить код создания спрайтшитов в собственном постпроцессоре импорта текстур (AssetPostprocessor). Этот код проверял местонахождение файла с текстурой и наличие рядом с ним xml-файла с описанием — в этом случае обработчик генерировал (или обновлял в случае переимпорта текстуры) соответствующие префабы и складывал их соответствующую папку.

Первые проблемы. Уровень с бомбой.

С первыми проблемами мы столкнулись, когда переносили бомбу — объект, который уничтожает всех врагов на экране. Изначально эффект, с которым происходил взрыв, создавал яркий ореол на весь экран. Естественно, при экспорте размер текстуры начал превышать все разумные пределы. На порядок. До “кармаковских” мегатекстур мы еще не доросли :), да и iOS тянет максимум 2048x2048.

С другими объектами начали возникать похожие проблемы — анимации, у которых были разные полупрозрачные эффекты (вспышки, сияния, арелоы) начинали занимать просто огромное место. Размер кадра для одного стрипа (а в одном стрипе могло быть несколько анимаций) был фиксированный. Получалось, что один большой кадр распирал всю анимацию, при этом большая часть текстуры была заполнена пустотой.

Первую трудность разрешили просто удалив из анимации плохие эффекты и заменив их на системы частиц Unity. Пришлось писать дополнительную логику, но другого выхода не было. Для второго случая пришлось добавить понятие составного SpriteSheet — это объект, который ведет себя как обычный спрайтшит с точки зрения внутриигрового API, но на деле содержит в себе множество других спрайтшитов с отдельными текстурами. При разметке Flash-клипа в метках указывалось, к какому составному SpriteSheet этот клип принадлежит. Таким образом мы вынесли все тяжеловесные анимации в отдельные ресурсы.

Заключение

Таким образом мы получили процесс, который позволял в пару кликов получать из Flash готовые для использования анимации. Конечно процесс можно было сделать лучше и правильнее, например, я не знал на тот момент о существовании ScriptableObject — он лучше подходит для этих задач.

Я намеренно не стал писать здесь простыни кода — любой, кому потребуется решить похожую проблему, без труда найдет всю необходимую документацию (я старался привести здесь ссылки на используемые материалы). Нам поставленную задачу решить удалось — мы получили возможность легко использовать векторные анимации, созданные во Flash, подготавливать текстуры для разных игровых разрешений и еще много бонусов. Конечно, Unity 4 подбросил немного дегтя в бочку, но эти проблемы тоже разрешаемы.

А что в итоге получилось желающие могут оценить в созданной нами игре Shadow Snake в App Store.

Если у кого есть замечания или вопросы, задавайте в комментариях.

Автор: justonce

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js