- PVSM.RU - https://www.pvsm.ru -
Хочу поделиться своим опытом работы со Spine — программой для создания скелетной анимации, специально заточенной под игры.
После просмотра официального гайда возникает много вопросов, поговорим про то, какие подводные камни ожидают нас при работе с этой программой на каждом этапе рабочего процесса (на примере Spine — Unity), как можно оптимизировать свою работу, а так же рассмотрим некоторые популярные фишки типа 3D эффекта. В статье будет много тяжелых гифок.
Сразу оговорюсь, для создания программной анимации в играх есть и другие решения, Dragon Bones, Spriter, Creature, Marionette studio, плагин Puppet 2D и наверняка найдутся другие, просто я как аниматор работаю в Spine.
Когда у нас на руках есть информация и понимание какие персонажи/анимации должны быть созданы для игры, отрисован необходимый материал — можно приступать.
Общая схема работы такова:
Первым делом необходимо подготовить рабочий материал из графических редакторов. Затем ассеты (assets, текстуры) импортируются в Spine и анимируются. На выходе мы получаем Json — файл в котором записаны все ключевые кадры трансформации костей, слотов и проч. Данный файл импортируется в движок, создается специальная skeleton data, которая добавляется на сцене в Spine game object, где наша анимация визуализируется по средствам mesh renderer, запуском можно управлять с помощью кода или же стандартным unity animator.
Непосредственно рабочий процесс в спайне выглядит следующим образом:
В качестве примера попробуем сделать анимацию вот такого персонажа:
На этапе подготовки текстур нам важно понимать сколько необходимо проекций персонажа, какая часть работы будет сделана покадрово, какая программно, как грамотно разрезать персонажа и подготовить ассеты.
Типичные ошибки:
А также недостаточное число проекций если персонаж меняет ракурс.
Часто у персонажей есть парные элементы с идентичными изображениями — руки, ноги, глаза, и проч. В таком случае целесообразно сохранить только одну текстуру, и использовать ее два, или более, раз.
В данном случае нам будет достаточно одной проекции, и ассеты художник отрисовал хорошо. Можно приступать к импорту в спайн.
Процесс импорта текстур можно существенно ускорить используя скрипт layers to PNG, который сохраняет каждый слой из фотошопа в отдельное png изображение, при этом записывает Json файл в котором содержится информация о расположении текстур, импортируя его в спайн мы получаем готового собранного персонажа.
Однако у такого способа есть ряд недостатков — скрипт сохраняет изображения без сжатия, что непрактично. Просто пересохранив слои через file-generate-image assets мы уменьшим вес изображения приблизительно в 10 раз.
Далее, необходимо не забывать разворачивать ваши в спрайты в горизонтальное или вертикальное положение, и стирать все лишнее, т.к. скрипт сохранит изображения прямо в том положении в котором они находятся в фотошопе.
Если для проекта необходима покадровая анимация (напр. огонь, спецэффекты, и проч.) — материалы необходимо отрисовать заранее. Далее с помощью adobe after effects и скрипта ae_to_spine мы можем в пару кликов перенести последовательность кадров в Spine.
Рекомендую заранее продумать концепцию наименования, материалы часто приходят в формате «слой 1 (копия) 5», это не слишком практично, для каждой текстуры в проекте необходимо сделать уникальное название, что бы не вызвать проблемы при запаковке атласов. Вполне пригоден вариант формата CharacterVyasya_Skin_a_Hand_R_1.
Тут во многом нам может помочь инструмент find and replace который позволяет быстро переименовывать, указывать путь для большого количества объектов.
Настраивая скелет для персонажа нужно уже думать о том, что, скорее всего, в процессе работы над игрой анимацию нужно будет корректировать, подправлять, поэтому желательно сделать его максимально гибким, что бы процесс правок был максимально простым и быстрым.
Тут может помочь введение дополнительных костей-контролов для разбиения движения по осям X и Y (т.к. в спайне остутствует функция separate dimentions).
Тут же маленький типс, если вдруг чувствуется нагромождение из за излишнего количества костей — попробуйте покрутить настройку bone scale:
Смотрите примеры готовых ригов из образцов поставляемых вместе со спайном, или в сети.
Так же полезные материалы можно искать на behanсe [9], форуме [10], соответствующих сообществах в социальных сетях.
Меш — Один из ключевых инструментов в спайне, накладывая на его текстуру мы получаем возможность ее деформировать, искажать, создавать иллюзию 3D.
При создании меша помните: чем меньше вертексов — тем проще контролировать анимацию.
Т.к. деформация меша потребляет ресурсы CPU, при создании сетки стоит руководствоваться принципом необходимого минимума, наглядно это можно рассмотреть на примере рига кончика хвоста динозавра:
Не забывайте про возможность дублирования целой иерархии меша вместе с костями и весами. Это поможет значительно сэкономить время при риге повторяющихся объектов.
В конечном итоге у нас возникает вопрос — а сколько вертексов можно использовать?
Разработчики спайна конкретно не отвечают на этот вопрос, и отсылают к вкладке Spine Metrics [11], где мы можем отследить суммарное количество элементов в сцене, но при этом говорят о необходимости проведения кастомных тестов производительности.
Важно помнить что трансформация меша, таймлайны, констрейны грузят CPU, а статичная геометрия — GPU. В общем, я бы советовал в случае работы над ключевыми персонажами не сильно заморачиваться по поводу точек, плюс минус десяток не сыграет никакой роли, однако в случае объекта из окружения, который будет повторяться сотню раз, каждый сэкономленный вертекс пойдет на пользу.
И так, когда наш персонаж настроен можно переходить к анимации:
Сама по себе анимация это очень большая тема и явно не для обсуждения в рамках одной статьи.
Тут я ограничусь банальными советами в ключе:
Это то за что так любят спайн — возможность деформировать изображение с помощью меша тем самым создавая трехмерный эффект.
Для себя я отметил несколько способов создания псевдо 3Д:
Наглядно принцип построения трехмерного эффекта можно рассмотреть на геометрических примитивах:
Анимируя кости создаем трехмерный эффект:
Можно сделать анимацией вертексов в меше, но как мы видим по сравнению с кубом точек значительно больше:
Аналогично кубу, кости в ключевых точках меша. По затраченному времени этот способ не лучше предыдущего:
Было бы гораздо более гибко свести риг под один глобальный контрол с помощью констрейнов, двигая одним управлять всеми костями:
То же самое, можно сделать без лишней массы костей,
Для этого каждому вертексу тщательно подбирается значение в весах. Такой способ можно считать оптимальным для округлых поверхностей.
Из примеров видно что анимация непосредственно точек в меше это один из самых негибких вариантов, который в случае необходимости будет трудозатратно переделывать. К этому стоит добавить что в некоторых других рантаймах, помимо юнити, эта фича не поддерживается. Поэтому рекомендую по возможности не трогать меш и управлять им с помощью костей.
По аналогии можно сделать деформацию любой геометрической формы, тем самым добавив вашей анимации выразительности.
И так, мы просидели несколько часов над ключевыми кадрами, мешами, и сделали анимацию персонажа:
Далее можно отправлять нашу анимацию в движок. Однако часто возникают ситуации когда внешний вид анимации в спайне и в рантайме существенно отличается, а т.к. каждое взаимодействие аниматор-программист занимает определенное время, лучше заранее провести тест анимации в рантайме, в ходе которого выявятся основные косяки, и только потом отдать работу будучи уверенным что все хорошо.
Если ваш аниматор не дружит с движком, можно использовать Skeleton Viewer [12]
Какие проблемы возникают наиболее часто:
Чаще всего такое происходит из за неправильной композиции текстуры — меш должен четко соответствовать размеру спрайта.
Происходит это потому что в рантайме анимация просчитывается не из дефолтного положения, а как бы из текущего. Т.е. если мы один раз включим текстуру и не выключим — она останется в таком положении во всех анимациях. Тоже самое и с другими ключами. Это скорее не баг, а фича, но к сожалению аниматор не видит реальной картины пока не импортирует свой материал в рантайм. Решить данный вопрос можно несколькими способами:
1) Проставить ключи на всех свойствах всех объектов в начале и в конце каждой анимации. На первый взгляд слегка муторно, но таким образом вы полностью обезопасите себя от нежданных сюрпризов. Использование фильтров и горячих клавиш ускорит процесс.
Красным выделена иконка фильтра объектов по костям и кнопка для быстрого разворачивания иерархии:
Горячие клавиши по умолчанию:
Key Active: L
Key Selected: ctrl + L
Key Dopesheet: ctrl + shift + L
Key Translation, Key Rotation, Key Scale, Key Shear, Key Color — нужно настраивать самому
2) Использовать скрипт setToSetupPose [13], который как бы и заставляет проигрываться анимацию из дефолтного состояния. Но такой метод имеет существенный недостаток — Setup Pose выставляется мгновенно, а рендер меняет картинку на соответствующую только со следующего кадра. Таким образом мы имеем проскакивание лишнего кадра между анимациями, выглядит это неприятно. Соответствующее issue уже стоит на доске у разработчиков.
Мы можем экспортировать из спайна Json, провести с ним какие-либо манипуляции, и импортировать обратно, получив определенный результат. Это очень мощный инструмент т.к. мы получаем доступ ко всем компонентам проекта, в свою очередь нам это может очень помочь в определенных ситуациях:
Часто возникает необходимость держать анимации в одной сцене, например как тут:
Для этого есть как минимум два способа: руками и скриптом.
Копируем куски кода из одного json в другой, в соответствующие категории: слоты к слотам, кости к костям, анимации к анимациям, и т.д. Что бы не возникло конфликтов, важно соблюсти корректность наименования объектов, что бы названия из одного json не совпадали с названиями из другого. Проще всего этого добиться заранее в спайне присвоив всем объектам в именах свой уникальный индекс типа _skel1_ и _skel2_. Этот способ слегка затратный по времени, но меня еще не подводил.
{
"skeleton": { "hash": "ZMTMZiuTD2M2gnBhJR0JLPQWOws", "spine": "3.4.02", "width": 0, "height": 0, "images": "" },
"bones": [
{ "name": "root_skel1_" },
{ "name": "bone1_skel1_", "parent": "root_skel1_", "length": 26.95, "rotation": 360, "x": 11.09, "y": -9.65, "color": "00ff00ff" },
{ "name": "bone2_skel1_", "parent": "bone1_skel1_", "length": 26.95, "x": 26.27, "color": "00ff00ff" },
{ "name": "bone3_skel1_", "parent": "bone2_skel1_", "length": 26.95, "x": 26.57, "color": "00ff00ff" },
{ "name": "bone4_skel1_", "parent": "bone3_skel1_", "length": 26.95, "x": 25.97, "color": "00ff00ff" }
],
"animations": {
"animation": {}
}
}
{
"skeleton": { "hash": "osF6oBu7PH6sMNfjN7pm2EwQ8fY", "spine": "3.4.02", "width": 0, "height": 0, "images": "" },
"bones": [
{ "name": "root_skel2_" },
{ "name": "bone1_skel2_", "parent": "root_skel2_", "x": 19.25, "y": 26.63, "color": "fff100ff" },
{ "name": "bone2_skel2_", "parent": "bone1_skel2_", "x": 27.14, "color": "fff100ff" },
{ "name": "bone3_skel2_", "parent": "bone2_skel2_", "x": 25.57, "color": "fff100ff" },
{ "name": "bone4_skel2_", "parent": "bone3_skel2_", "x": 27.14, "color": "fff100ff" }
],
"animations": {
"animation": {}
}
}
{
"skeleton": { "hash": "ZMTMZiuTD2M2gnBhJR0JLPQWOws", "spine": "3.4.02", "width": 0, "height": 0, "images": "" },
"bones": [
{ "name": "root" },
{ "name": "root_skel1_", "parent": "root" },
{ "name": "bone1_skel1_", "parent": "root_skel1_", "length": 26.95, "rotation": 360, "x": 11.09, "y": -9.65, "color": "00ff00ff" },
{ "name": "bone2_skel1_", "parent": "bone1_skel1_", "length": 26.95, "x": 26.27, "color": "00ff00ff" },
{ "name": "bone3_skel1_", "parent": "bone2_skel1_", "length": 26.95, "x": 26.57, "color": "00ff00ff" },
{ "name": "bone4_skel1_", "parent": "bone3_skel1_", "length": 26.95, "x": 25.97, "color": "00ff00ff" },
{ "name": "root_skel2_", "parent": "root" },
{ "name": "bone1_skel2_", "parent": "root_skel2_", "x": 19.25, "y": 26.63, "color": "fff100ff" },
{ "name": "bone2_skel2_", "parent": "bone1_skel2_", "x": 27.14, "color": "fff100ff" },
{ "name": "bone3_skel2_", "parent": "bone2_skel2_", "x": 25.57, "color": "fff100ff" },
{ "name": "bone4_skel2_", "parent": "bone3_skel2_", "x": 27.14, "color": "fff100ff" }
],
"animations": {
"animation": {}
}
}
В результате имеем все в одном проекте:
Проблемы могут возникнуть в проектах с скинами, по возможности старайтесь не менять иерархию костей.
Более сложный пример с лягушкой:
(Осторожно, длинные файлы)
Жук [14]
Лягушка [15]
Жук+Лягушка [16]
Добрые люди написали специальную тулзу для мержинга. Ознакомиться и скачать можно по ссылке [17]. Использовать ее достаточно удобно, включен автоматический ренейминг объектов, однако я не раз сталкивался с ошибками.
В спайне отсутствует вложенность композиций (аналог прекомпоз в After Effects или символ во Flash), однако, как показывалось выше, есть возможность продублировать объекты, с сохранением всех зависимостей, но ключи анимации в таком случае не копируются. Не сложно догадаться что, для того что бы не делать анимацию заново, можно переназначить ее на дубликат костей, для этого надо всего лишь перебить в Json имена. Опять же, это проще сделать если у каждой кости будет свой уникальный индекс.
Экспортируем Json и открываем его текстовым редактором. Код анимации walk_1 копируем, находим там все участки _skel_1_:
"animations": {
"walk_1": {
"bones": {
"US_2_skel_1_": {
"rotate": [
{
"time": 0,
"angle": -42.21,
"curve": [ 0.25, 0, 0.75, 1 ]
},
{
"time": 0.4,
"angle": -0.92,
"curve": [ 0.25, 0, 0.75, 1 ]
},
{ "time": 0.8, "angle": -42.21 }
]
},
....
заменяем их на _skel_2_
....
"US_2_skel_2_": {
"rotate": [
{
"time": 0,
"angle": -42.21,
"curve": [ 0.25, 0, 0.75, 1 ]
},
{
"time": 0.4,
"angle": -0.92,
"curve": [ 0.25, 0, 0.75, 1 ]
},
{ "time": 0.8, "angle": -42.21 }
},
...
Вставляем обратно. Таким образом мы переназначили анимацию на другие кости. Сохраняем json, и импортируем его в спайн путем file — import data. Теперь у нас два бегающих муравья.
Проекты сохраненные в более новой версии будут не совместимы со старыми. Иногда это может стать проблемой, и для ее решения есть несколько способов:
"skeleton": { "hash": "", "spine": "3.4.02", "width": 0, "height": 0, "images": "" },
Поможет если между версиями небольшой промежуток, и нет принципиальных различий в алгоритмах работы анимации.
Ознакомиться с принципом работы и скачать можно по ссылке [18].
Спасибо за внимание, наверняка если вы дочитали статью до этого момента у вас возникли вопросы или замечания, с удовольствием прочитаю все в комментариях.
P.S. Статья писалась аниматором по большей части для аниматоров, если вы программист и у вас «рукалицо», можете высказаться в комментариях.
Автор: borovikmotion
Источник [19]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/unity3d/212947
Ссылки в тексте:
[1] подробнее: http://ru.esotericsoftware.com/spine-images#Photoshop
[2] Подробнее : http://esotericsoftware.com/forum/viewtopic.php?f=11&t=2983
[3] Søren Nielsen: https://www.youtube.com/channel/UC_ijsuTUdxMjjM1P30f8Gaw
[4] Hwadock Jang: https://www.youtube.com/user/hwadock1/videos
[5] Charles Duchesne: https://www.youtube.com/user/Lhescar/videos
[6] Dao Le Trong: https://www.youtube.com/channel/UC56PA4QoDwdiX0qP5X-vB2A/videos
[7] Spine progress: https://youtu.be/OU-MkV4N67Q
[8] Walk test: https://www.youtube.com/embed/JHoigf53-O0
[9] behanсe: https://www.behance.net/search?search=spine+animation+
[10] форуме: http://ru.esotericsoftware.com/forum/viewforum.php?f=5&sid=9d77051b99070534b227a07930749766
[11] Spine Metrics: http://ru.esotericsoftware.com/spine-metrics
[12] Skeleton Viewer: http://ru.esotericsoftware.com/spine-skeleton-viewer
[13] скрипт setToSetupPose: https://gist.github.com/pharan/a910e129337b71f57a92
[14] Жук: https://gist.github.com/Borovikmotion/eb1dc1b772998e441fc5e0e598873946#file-beatle
[15] Лягушка: https://gist.github.com/Borovikmotion/eb1dc1b772998e441fc5e0e598873946#file-frog
[16] Жук+Лягушка : https://gist.github.com/Borovikmotion/eb1dc1b772998e441fc5e0e598873946#file-merged-beatle-frog
[17] по ссылке : http://esotericsoftware.com/forum/Skeleton-Merger-Tool-5070?sid=c7593ff312f890f059ee5fe8688240c2
[18] по ссылке: http://ru.esotericsoftware.com/forum/Spine-editor-and-runtime-version-management-6534
[19] Источник: https://habrahabr.ru/post/315950/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.