Неделя 45-54 (август 5 – октябрь 4): Анимации и годовщина.

Тут самое время афигеть от того, что я уже два месяца не писал отчетов о своей работе. В свое оправдание могу сказать только что я впервые за довольно долгое время болел дольше выходных, а потом отпуск и все такое. Кстати я получил возможность проверить работоспособность моей игры на мобильном интернете в стране свободы и манго по 20 рублей за килограмм.

И честно говоря я несколько подзабыл на чем остановился в прошлый раз. Помню что у меня были непреодолимые страдания по поводу контента, которые я не смог решить даже обновив редактор. По сути мои страдания уперлись в то, что для проверки одной очень важной для дерева крафта идеи мне надо дописать одну довольно сложную функцию на сервер – проверку рестрикшенов. Я прям очень не хочу этим заниматься.

В общем я уперся в очень серьезный тупик. В качестве выхода из тупика была принята идея сделать шаг в сторону и заняться хоть чем-нибудь что может принести пользу. Этим чем-нибудь стала визуальная часть моей игры. Я снова расчехлил MagicaVoxel и начал прикидывать как бы мне хотелось чтобы выглядел персонаж.

Модель

Идея у меня примерно такая: взять персонажа из MineCraft и как-то его модифицировать так чтобы он выглядел не хуже, но и не так же. Не думаю что кто-нибудь помнит но на неделе 19 я уже брался за это дело. Я даже сделал модельки меча, шлема и какого-то балахона чтобы показать как прикольно смотрелось бы если бы шмотки были отдельными моделями. Меня тогда только переклинило по количеству пикселей. Да, для пиксельной текстуры, создаваемой в MagicaVoxel действительно важно будет ли у тебя голова 8х8 или 9х9 – можно впихнуть нос отличный от картошки, например. Для игрового мира же, создаваемого в Unity это не важно совсем. Там другая сетка координат. То есть чтобы сделать меч толщиной 1 пиксель (как в оригинале) не обязательно делать его на модели персонажа (опять же как в оригинале) и мучиться от того что одно-пиксельный меч плохо ложится в четырех-пиксельную руку.

Но все же есть одна область в которой количество пикселей все-таки важно и это так же показано было том посте на 19й неделе: одежда. Дело в том, что персонаж должен не прост стоять в Т-позе, он должен быть анимирован. И если я хочу даже помыслить о том, что одежда будет отдельной моделькой, то мне нужно что-то делать с телом.

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

Тут наверное надо сделать лирическое отступление на тему: “а зачем вообще мутить такую сложную и наверняка не самую экономичную по отношению к ресурсам игрового устройства систему?” Ответ на этот вопрос довольно банален, сколь и печален. Рисовать-то я не умею. Я просто не смогу нарисовать достаточно качественные и достаточно разнообразные предметы. А вот напиксельартить их я смогу. И выглядеть это будет не как скан моих детских рисунков (с тех пор мало чего изменилось), а как стильное инди.

Есть еще одна неприятность: персонаж является довольно сложным объектом в котором многие вещи могут друг с другом плохо сочетаться. Например шапки и волосы. Если прическа короткая и ее модель выпирает меньше чем модель шапки, то можно сказать что волосы уместились под шапкой и все ок. А если волосы длинные? Если у персонажа ирокез? Или еще круче. Например, мы просто убираем торс персонажа когда надеваем на него доспехи и отображаем только эти доспехи. Но что если у нас майка? Допустим мы можем включить в состав майки часть торса… но что если у нас тела могут быть разного цвета (чтобы нас не обвинили в расизме)? Взрослые люди наверное умеют перекрашивать торс если он является частью майки так же как они перекрашивали торс без одежды. Я же буду просто надевать майку поверх тела каким бы оно ни было.

И вот так у нас появляется дополнительный пиксель. Этот пиксель разносит ноги на два пиксель в сторону, что делает тело шире. Чтобы сохранить пропорцию, надо сделать его так же и толще. Но не слишком, ведь ноги по сути должны оставаться квадратными в сечении “столбиками”. Но достаточно чтобы персонаж не выглядел стоящим враскаряку. Еще есть рукава и… как называется часть одежды, которая только на торсе? Еще два пикселья в ширину. Но так чтобы персонаж получался не слишком плечистым. Отдельно стоит вопрос толщины ткани. Но выработав принцип, ответить на этот вопрос становится значительно проще.

Я тут еще попробовал сделать “сглаживание”. Так как прообразом персонажа являюсь я сам, то у него есть пузо и нет груди.

Анимация

Чтобы хоть что-то увидеть на экране нужны две вещи: механизм перемещения и анимации, которые будут это перемещение изображать. В Unity есть два способа анимировать персонажей: самостоятельно, создавая анимации в редакторе анимаций или в каком-то 3D-редакторе и импортируя их в игру, либо использовать механизм аватаров и тырить подходящие анимации гденипоподя.

Первый вариант очень простой на входе: собрал объект персонажа и давай его аниминровать – но какого-либо результата за обозримое время этим способом добиться невозможно. В общем, одной попытки сделать анимацию ходьбы достаточно чтобы сесть в угол и горько заплакать от безальтернативности использования аватаров. Плюс сюда накладывается безумный процесс совмещения hand-made анимаций с перемещением, что уж совсем смахивает на план “я буду упорно трудиться и через 10 лет получу велосипед оригинальной конструкции”.

Это моя первая попытка сделать анимации ручкам. Получилось даже мило.

Второй вариант – использование аватаров – пугает тем, что основан на скелетной анимации. Я уже решил, что персонажи у меня состоят из довольно отдельных кубиков и я как-то не планировал разбираться в процессе создания скелета под эти кубики. Не то чтобы у меня остался какой-то выбор. Плюс к тому, скелет означает что надо каким-то образом настроить риг моего персонажа. Риг – это то как модель реагирует на перемещение той или иной кости скелета. Чтобы тело не заминалось и сохраняло свойственную оригиналу природную гладкость поверхности. У меня же кубики! Они не должны гнуться!

Есть такой сервис Mixamo. Он позволяет загрузить свою модель и возвращает ее с каким-то ригом, который тут же можно опробовать на довольно обширной библиотеке антропоморфных анимаций. Нет.

Но делать анимации самому было еще худшим вариантом. И я запустил Blender, собрал из экспортированных из MagicaVoxel кубиков тело, и начал смотреть как делать скелеты. В общем секас с этим скелетом (вернее скелета со мной) даже описывать не буду. Он меркнет по сравнению с тем, что я пережил потом. Если коротко, то я выяснил, что оказывается, в Блендере можно расположить кубики в иерархии похожей на иерархию скелета и этого будет достаточно чтобы настроить в Unity аватара, и использовать сторонние анимации. Собственно эту иерархию Unity и читает как скелет. Даже не знаю почему Юнитя при этом не позволяет его редактировать. Это окажется особенно важно немного позже.

Все выглядит так будто нужную иерархию можно собрать прям в Unity, но по какой-то непонятной лично мне причине она не дает этого сделать.

У Блендера, как у любой уважающей себя программы, есть какой-то свой формат хранения данных. Unity даже умеет его читать, но вот беда – не умеет из него создавать аватары (вернее умеет, но выбирать руками коревой объект – это какое-то днище, особенно учитывая что от блендера мне нужна только иерархия и ничего больше). Решается это вроде бы просто: экспортируешь сцену в нужном формате и работаешь дальше. Так и было бы если бы Блендер не был проклятой богом адской хренью, посланной нам боженькой за грехи наши.

Как-то так исторически сложилось, что в Unity плоскость земли имеет координаты X, Z (ох уж это 2D-шное наследие, которого у Юнити не было), а 3D-редакторы по-умолчанию считают плоскостью земли X, Y. Говорят, что в нормальных 3D-редакторах это можно настроить. Но нормальные редакторы стоят денег. А мы не любим платить за то, чем не планируем пользоваться, так ведь? Так вот, при экспорте в VBX Блендер предлагает поменять вертикальную ось с Z на Y. Не позволяйте себя обмануть. Ничего он не меняет. Он тупо поворачивает сцену по оси X.

Не то чтобы это было страшно… просто в игре неанимированная модель будет лежать на спине. Или на животе. Потому что они по-умолчанию будут иметь какой-то поворот, полученный при экспорте. Про неанимированную важное уточнение: применение анимации сбрасывает настройки положения корня объекта в ноль – то есть если неанимированный персонаж лежал на спине, то анимированный будет стоять вертикально как должен. Но вот лежащего на спине персонажа ставить на ноги средствами юнити нельзя – анимации повернуться. Бдыщ!

Это еще не все. При некоторых настройках экспорта персонаж может сломаться, так что анимации будут его взрывать или кукожить.

Есть еще одна интересная особенность работы Блендера. В Unity есть такое понятие как локальные и глобальные координаты. Все объекты которые находятся где-то в глубине иерархии в инспекторе будут показывать локальные координаты относительно родителя. При смене родителя система автоматически пересчитывает локальные координаты не ломая расположения объекта. В Блендере же в глубинах иерархии объекты могут показывать как локальные, так и глобальные координаты. Собственно из-за них и взрывались персонажи. Происходило это из-за того что некоторые объекты я сначала двигал, а потом расставлял в иерархии, а другие наоборот. Короче я раз пять пересобирал персонажа чуть ли не с нуля.

Из-за откровенно уебищного управления в Блендере, даже сориентировать сцену нормально не получается. Но тут видно где находится “земля”, и в каком положении находится мой скелет. Кубики я использую как метки – на них удобно ориентироваться при надевании частей тела и шмоток.

Перемещение

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

Дело в том, что анимация, навигация и управление фактически добавляют в персонажа 3 новых класса, каждый из которых имеет определенный уровень контроля над поведением персонажа. Только анимация устроена так, что в ней все относительно однозначно: анимация должна проигрываться со скоростью соответствующей перемещению. Но и тут Юнити схитрила.

Итак есть агент – это, скажем так, характеристика объекта, позволяющая ему двигаться по каким-то образом ограниченной плоскости. У этого агента есть скорость передвижения и прочие настройки нам не слишком важные. К этому агенту прибавляется контроллер анимаций и собственно сам аниматор. Контроллер своих скоростей не имеет, он предназначен для того, чтобы сдружить скорости агента, со скоростями анимаций.

И вот тут есть хитрость. В стандартных ассетах и в уроке с навигацией используется набор анимаций включающих в себя стоящий на месте айдл, ходьбу и бег. Айдл и бег – это крайние состояния, медленнее и быстрее которых персонаж без заметных глазу артефактов передвигаться не сможет. Но между ними есть пространство промежуточных состояний работу которых обеспечивает дерево смешивания (blend tree). Эта штука, позволяет подобрать комфортную глазу скорость перемещения персонажа по экрану так чтобы его анимация выглядела естественной (на сколько это возможно) независимо от того, где она находится между айдлом и бегом. Лишь бы собственно был этот набор: айдл, ходьба и бег. В наших же условиях понятно что нет вообще никакой причины не использовать уже имеющийся набор.

Осталось только в игру вставить.

З.Ы.: Ну и да, 54я неделя в заголовке намекает на то, что проектом этим я занимаюсь уже больше года. Спасибо.

Оглавление