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

досвід
Буквально нещодавно ми з товаришами запустили наш перший проект під iOS - іграшку про змійку Shadow Snake. Хотілося випробувати розробку під iPad, тому вирішили перенести готовий проект, зроблений на Flash, тим більше, що механіка дозволила дуже гармонійно використовувати можливості сенсорного управління.

Звичайно, першою ідеєю було спробувати AIR SDK – проект запустився, але з динамічної аркади він перетворився на аркаду "походову". FPS був дуже низьким через те, що майже вся графіка у флешці була векторною, а мобільний AIR з нею не дуже товаришує. Я вже не пам'ятаю точно, який AIR на той момент був доступний (2.x або перша версія 3.x), але ми проводили експерименти як з векторною графікою, так і з іншим проектом, зробленим у растрі на Flixel. Результати не дуже нас потішили. Зараз, я дивлюся, прогрес зрушив, Adobe навіть випустила якийсь новий компілятор. У будь-якому випадку, тоді було вирішено використовувати Unity 3D.

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

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

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

Як відкрити SWF і перетворити векторні зображення на PNG або JPEG? Правильно! Потрібно використовувати Flash. Як зберегти отримані результати на диск? Правильно! Потрібно використати AIR.

Розтеризація була здійснена за допомогою BitmapData і PNGEncoder зподальшим збереженням у файл за допомогою FileStream.

Необхідно було побудувати процес таким чином, щоб анімації експортувалися з найменшими рухами тіла. А саме, щоб усі метадані (назви анімацій, розкадрування, масштаб кадрів, параметри зациклювання) можна було редагувати у середовищі Flash.

Adobe Flash не дозволяє додавати до MovieClip додаткову інформацію, тому довелося запровадити кілька угод. Наприклад, імена кліпів, які потрібно було експортувати, починалися з префіксу "e_". Цей префікс відрізався для формування підсумкових файлів. Для розмітки анімації та завдання її властивостей використовувалися мітки кадрів, задані у певному форматі. У результаті вийшов зручний синтаксис, а структура кожного експортованого MovieClip виглядала наступним чином:

практичний

На виході програми виходив набір спрайтлистів та їх опис у форматі XML. Кому цікаво, можуть покопатись у вихідниках. Вихідники непідготовлені, недокументовані, as is:). Просто ніколи зараз оформляти їх у "продукт", але їх можна розтягнути "на запчастини".

Окремо зазначу, що перегортання кадрів під час розтеризації у завантаженому ззовні MovieClip потребує “специфічних” прийомів. Це з поведінкою вкладених кліпів — можуть з'являтися кілька кадрів, потім зникати у процесі анімації. Тому для кожного нового проходу краще створювати об'єкт заново. Для отримання списку доступних кліпів у завантаженому файлі використовувалася бібліотека SWFExplorer.

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

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

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

Перший відповідав за власне виведення спрайту в ігровий простір. Він створював стандартні для Unity компоненти MeshFilter та MeshRenderer та наповнював їх даними зі SpriteSheet. Таким чином вдалося використати смачні фічі, а ля Dynamic Batching.

досвід

SpriteSheet ж містив посилання на текстуру, що підключається, список анімацій, кадрів та інші налаштування - всю ту інформацію, яка вивантажувалася з SWF. Вирішили зберігати її саме засобами Unity, щоб мати можливість коригувати параметри інструментами середовища. SpriteSheet'и генерувалися автоматично у вигляді готових префабів, які потім розміщувалися на сцені.

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

Перші проблеми. Рівень із бомбою.

З першими проблемами ми зіткнулися, коли переносили бомбу – об'єкт, який знищує всіх ворогів на екрані. Спочатку ефект, з яким відбувався вибух, створював яскравий ореол на весь екран. Звичайно, при експорті розмір текстури почав перевищувати всі розумні межі. На порядок. До "кармаківських" мегатекстур ми ще не дорослі :), та й iOS тягне максимум 2048x2048.

З іншими об'єктами почали виникати схожі проблеми — анімації,у яких були різні напівпрозорі ефекти (спалахи, сяйва, арелої) починали займати просто величезне місце. Розмір кадру для одного стрипу (а в одному стрипі могло бути кілька анімацій) було фіксовано. Виходило, що один великий кадр розпирав всю анімацію, причому більшість текстури була заповнена порожнечею.

Першу труднощі дозволили просто вилучивши з анімації погані ефекти та замінивши їх на системи частинок Unity. Довелося писати додаткову логіку, але іншого виходу не було. Для другого випадку довелося додати поняття складеного SpriteSheet - це об'єкт, який веде себе як звичайний спрайтшит з точки зору внутрішньоігрового API, але насправді містить безліч інших спрайтшитів з окремими текстурами. При розмітці Flash-кліпу в мітках вказувалося, до якого складового SpriteSheet цей кліп належить. Таким чином, ми винесли всі великовагові анімації в окремі ресурси.

Висновок

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

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

А у нас тут можна отримати грант на тестовий період Яндекс.Хмари. Стоїтьлише у полі «секретний пароль» ввести «Хабр»