Практически опит в мигрирането на ресурси от 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 изглеждаше така:

ресурси

Резултатът от приложението беше набор от spritelists и тяхното описание в XML формат. Тези, които се интересуват, могат да се разровят в изходния код. Източници неподготвени, недокументирани, както е :). Просто сега няма време да ги формализираме в „продукт“, но могат да бъдат разглобени „за резервни части“.

Отделно отбелязвам, че обръщането на кадри по време на растеризиране във MovieClip, зареден отвън, изисква „специфични“ техники. Това се дължи на поведението на вложените клипове - те могат да се появят за няколко кадъра, след което да изчезнат по време на анимацията. Следователно за всяко ново преминаване е по-добре да създавате обект наново. Библиотеката SWFExplorer е използвана за получаване на списъка с наличните клипове в изтегления файл.

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

След като ресурсите се преобразуват в нормална за обработка форма, списъците с спрайтели с техните метаданни трябва да бъдат представени във формат, разбираем за Unity.

Решихме да не използваме готови 2D рамки за Unity,защото трябваше да тества технологията, да придобие нов опит и да разбере по-добре как да прави игри в тази среда. Затова бяха изобретени 2 специални компонента - AnimatedSprite и SpriteSheet.

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

ресурси

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

Резултатът от работата на AIR конвертора се състоеше от png и xml файлове, така че по това време беше най-удобно да поставим кода за създаване на spritesheets в нашия собствен постпроцесор за импортиране на текстури (AssetPostprocessor). Този код проверява местоположението на текстурния файл и наличието на xml файл с описание до него - в този случай манипулаторът генерира (или актуализира, ако текстурата е импортирана повторно) съответните префабове и добавя съответната им папка.

Първи проблеми. Ниво на бомба.

Срещнахме първите проблеми, когато носехме бомба, обект, който унищожава всички врагове на екрана. Първоначално ефектът, с който се получи експлозията, създаде ярък ореол върху целия екран. Естествено, при експортирането размерът на текстурата започна да надхвърля всички разумни граници. На поръчка. Все още не сме израснали до мегатекстурите на „Кармаков“ :), а iOS дърпа максимум 2048x2048.

Подобни проблеми започнаха да възникват и с други обекти - анимации,които имаха различни полупрозрачни ефекти (светкавици, сияние, ареоли) започнаха да заемат огромно място. Размерът на рамката за една лента (и може да има няколко анимации в една лента) беше фиксиран. Оказа се, че един голям кадър разбива цялата анимация, докато по-голямата част от текстурата е изпълнена с празнота.

Първата трудност беше решена чрез просто премахване на лошите ефекти от анимацията и замяната им със системи от частици Unity. Трябваше да напиша допълнителна логика, но нямаше друг изход. За втория случай трябваше да добавя концепцията за съставен SpriteSheet - това е обект, който се държи като обикновен spritesheet от гледна точка на API в играта, но всъщност съдържа много други spritesheet с отделни текстури. Когато етикетирате Flash клип, етикетите показват към кой SpriteSheet компонент принадлежи клипът. Така преместихме всички тежки анимации в отделни ресурси.

Заключение

Така получихме процес, който ни позволи да получим готови за използване анимации от Flash с няколко кликвания. Разбира се, процесът можеше да се извърши по-добре и по-правилно, например, тогава не знаех за съществуването на ScriptableObject - той е по-подходящ за тези задачи.

Съзнателно не написах листове код тук - всеки, който трябва да реши подобен проблем, лесно ще намери цялата необходима документация (опитах се да дам връзки към използваните тук материали). Успяхме да решим поставената задача - получихме възможност лесно да използваме векторни анимации, създадени във Flash, да подготвим текстури за различни резолюции на играта и много други бонуси. Разбира се, Unity 4 хвърли муха в мехлема, но тези проблеми също са разрешими.

И тук можете да получите грант за тестов период на Yandex.Cloud. Разходисамо в полето "тайна парола" въведете "Habr"