Анатомия сокола
Недавно мы объявили о разработке игры Falcon Age о выращивании взрослой птицы из птенца сокола и совместном противостоянии силам, стремящимся колонизировать планету. Falcon Age выйдет в 2019 году на PS4 и PS VR.
На прошлой неделе мы показали игру на PAX и получили замечательные отзывы, особенно о самом соколе. Давайте подробно рассмотрим его дизайн, настройку анимаций и рига, ИИ и навигацию, технологию создания перьев и звуки хищника.
Дизайн сокола
Рассказывают Чандана Эканаяке и Дэрран Хёрлбат.
В дизайне сокола сочетаются разные виды хищных птиц. Наша соколиха размером с беркута, дерётся как ястреб, внешне напоминает и орла, и ястреба, имеет хохолки, как у совы, а уход за ней осуществляется, как за соколом. Она одна из последних представительниц своего вида в нашем мире, и мы хотели сделать её внешний вид уникальным и подходящим для сюжета. При этом во время игрового процесса она должна выделяться на фоне неба и пустынь.
Одним из первых источников вдохновения для создания Falcon Age стали видео беркутов, охотящихся на крупных горных козлов. Мы начали проводить исследования по соколиной охоте, и нас появилась идея приручения сокола и создания на основе этого механик и геймплея. На раннем этапе разработки мы создали грубый прототип, чтобы протестировать наши концепции. Как только мы впервые свистом подозвали птицу в VR, и увидели, как её масштаб меняется, она приближается к нам и садится на руку, нам стало понятно, что это может стать основой уникальной игры.
Анимации и риг
Рассказывает Аунг Зау Оо.
Отслеживание лап сокола
Существует множество вариантов анимирования, но ни один из них не мог простым способом решить нашу задачу отслеживания лап сокола. Системы с инверсной кинематикой, root motion и другие сложные плагины позволили бы нам справиться с работой, будь у нас команда побольше и достаточно времени. Мы хотели добиться более предсказуемого результата, поэтому выбрали решение на основании множества поз, созданных в 3dsmax.
Однако самой важной причиной отказа от IK стало то, что это был наилучшее решение, которое я нашёл за пару дней. В начале проекта мы так быстро собирали прототип, что у нас не было времени на рассмотрение других доступных решений. Это был самый надёжный и наименее неуклюжий способ из найденных мною, поэтому с тех пор мы придерживаемся его. Не нужно чинить то, что не сломано.
Вот как я представлял смешивание движения когтей птицы в реальной жизни. Шар — это кулак, прикреплённый к VR-устройству управления движением. У этого способа есть ограничения. Когти должны иметь возможность огибать большую часть кулака, и поза кулака должна быть как можно более сферической.
Заметьте, что голова и ноги находятся на одном уровне иерархии у таза. Это упрощает маскирование костей и создание отдельных blend trees. Не обращайте внимания на слово «eagle» («орёл») в названии. Это было просто название временного ассета до того, как мы определились с дизайном птицы.
Краткая версия того, как это было сделано: кулак — это шар, а лапы вращаются вокруг шара с помощью 30 поз смешивания и анимации перебирания лапами, чтобы вернуть их обратно к центру, когда шар (движущаяся рука) поворачивается слишком далеко.
30 поз смешивания (Blend Poses) на шаре
Анимация переступания позволяет вернуть лапы на центр
Смешивание начинается заново после короткой анимации переступания из нового поворота руки. По словам нашего программиста Джастина, он реализовал это обычными формулами кватернионов и линейной алгебры. А я используют три значения float, которые он даёт мне, и передаю их в эти состояния смешивания анимаций.
У птенца второй сустав указательного пальца обрабатывается как шар.
Единственный пограничный случай, в котором идея с шаром не работает — это когда перчатка направлена прямо вниз, как показано на рисунке ниже.
С этим случаем мы могли справиться различными способами. Одно из решений: добавить коллайдер на часть перчатки на предплечье коллайдер, чтобы птица взлетала, когда произойдёт коллизия с ним. Но в конце концов решили оставить всё как есть. Это более дружелюбно к игроку: можно почесать своё левое бедро, а птица в VR при этом не улетит. Кроме того, большинство людей никогда не наклоняют так руки во время игры.
Только если они по каким-то причинам не играют, стоя на голове.
В стойке на голове все анимации будут выглядеть неверными или сломанными.
Отслеживание головы сокола
Вкратце расскажу, как мы этого добились; голова (bone_Head) — это первый дочерний элемент самого верхнего объекта в скелетной иерархии птицы (bone_Root ).
Позиция (не поворот) Bone_Root следует за позицией контроллера движения и bone_Head противодействует этому движению. По сути, это иерархия из двух объектов, в котором смешивание позиций используется для противодействия движению родительского объекта, чтобы сохранить глобальную позицию дочернего объекта. Остальная часть тела птицы использует смешивание 27 поз для как можно более естественной позиции птицы.
С учётом размера взрослой птицы, перемещение на 12 см по всем осям (куб размером 24x24x24) оказалось идеальным для получения эффекта стабилизатора без слишком сильного вытягивания шеи. Голова будет двигаться на границе этого диапазона, и когда рука с отслеживанием движения перестанет двигаться, новая позиция будет считаться новым центром, вокруг которого создаётся другой куб со стороной 24 см. С математической точки зрения, стабилизация головы — это просто векторное преобразование со множеством различных довесков для ограничения скорости, начала и конца перехода, перемещения точки стабилизации, когда слишком удаляется от тела, а птица всё ещё находится в области.
Навигация и ИИ птицы
Рассказывает Джастин Лэлоун.
Когда птице скучно
Чаще всего сокол подчиняется приказам Ары (главной героини игры) и следует за ней. Если слишком долго стоять в одной области, пока птица просто летает кругами или если отпускать её, не отдавая приказов, то она начнёт сама искать себе занятие в округе — обычно охотиться или приземляться на разные важные точки рельефа. Также она берёт на себя инициативу, когда сидит на Аре и кто-то пытается схватить её, и любит показывать Аре следующую лунку при игре в молниевый гольф.
Солнце, ослепляющее жертву
Некоторые виды добычи, например кролики, очень пугливы, и когда они видят, как сокол ныряет в воздухе, пытаясь их схватить, то сбегают к ближайшей норе. Им гораздо сложнее заметить птицу Ары, когда она приближается с солнечной стороны, поэтому можно упростить поимку добычи, если уделять внимание тому, откуда падает свет, и посылать птицу с этого направления. С другой стороны, может быть вполне достаточно и просто нырять вниз с высоты, потому что птица сможет набрать бОльшую скорость, прежде чем её заметят, давая жертве меньше времени на побег.
Заходим быстро и со стороны солнца, чтобы точно схватить добычу.
3D-навигация сокола
Обычно в стандартном наборе игрового движка нет механизмов надёжного перемещения летающего животного в 3D-пространстве, которое при этом выглядело бы естественно. У нас есть примерно три уровня логики навигации птицы, выполняемых для перемещения птицы из точки A в точку Б, позволяющие не слишком усложнять систему и не застревать в углах.
Для высокоуровневой навигации, позволяющей находить маршрут по миру, мы строим 3D-граф навигации и используем для поиска пути алгоритм A*. В данной реализации достаточно уникально то, что для выполнения всех операций по поиску пути алгоритмом A* мы используем довольно новую систему задач Unity. Она обеспечивает быстрый поиск, не нагружающий основной поток, что оставляет больше времени для ИИ, физики и других аспектов. БОльшая часть графа генерируется автоматически, а для пролёта через узкие проёмы, например через окна, соединения размещаются вручную, потому что они малы или требуют подлёта под правильным углом.
Фиолетовая линия — это приблизительный путь для облёта больших скал посередине, где начинает полёт сокол и стоит Ара. Птица не стремится особенно близко следовать по этой линии; если бы это было так, она бы совершала очень странные и резкие повороты, поэтому если можно без помех добраться до следующей части пути, то она направляется туда.
Иногда на пути ей могут попадаться мелкие или подвижные объекты. Сокол смотрит вперёд и пролетает над или рядом с этими объектами. Скала достаточно велика, чтобы выполнять навигацию вокруг обычным алгоритмом A*, но я заставил его пока «забыть» об этом. Здесь чтобы обогнуть скалу, птица поворачивает влево — красные линии показывают, куда она смотрела в течение последних нескольких кадров. Обычно я стараюсь так не делать, но навигация A* может заставить птицу пролетать под арками или мостами.
Последний уровень логики полёта птицы — это сама логика маневрирования, выбор того, насколько быстро решает лететь птица, насколько ей нужно подняться или опуститься, как быстро поворачивать, как она применяет физическое ускорение, какие ограничения накладываются на её действия, чтобы добраться в конечную точку. Эти данные передаются в систему анимаций, сообщая, насколько активно птица работает, в каком типе позы она должна находиться, должна ли она делать вираж, и т.д. С этой системой довольно сильно связано уклонение от объектов, но вся навигация A* выполняется полностью отдельно. Здесь используется большой объём математики и логики.
Перья и рендеринг
Рассказывает Бен Голус.
Небольшие перья на теле, или контурные перья нашей птицы колышутся от ветра и реагируют на приглаживающие их руки игрока, чтобы добавить более глубокое ощущение тактильной интерактивности. Способ реализации перьев в демо для PAX был хаком, поэтому я надеюсь заменить его до выпуска игры. (Разумеется, это значит, что именно это решение будет реализовано в готовой игре.) Если вкратце, то каждое мелкое перо птицы считается несколькими шейдерами травы или растительности. Для вычисления простого шума колебаний перьев вычисляется несколько накладывающихся синусоид, что придаёт перьям естественности. Их временные изменения смещены на случайное для каждого пера значение, хранящееся в цвете вершины, а движение колыхания тоже масштабируется в соответствии с цветом вершины. Это означает, что основа перьев, в отличие от концов, не движется. Также это значит, что длинные перья движутся больше, чем короткие.
Мы хотим, чтобы перья не двигались в случайных направлениях, как в большинстве шейдеров травы, поэтому нельзя использовать направления мирового или локального пространства. Плюс они находятся на меше со скиннингом, что делает направление ещё более динамичным. Поэтому я использовал сочетание нормалей и касательных вершин перьев, чтобы перья колыхались внутрь и наружу, а также в разные стороны относительно их ориентации. Система не очень точная, но при таких небольших перемещениях ошибки почти не будут заметны.
Для обработки взаимодействий с рукой в руке игрока есть скрипт, отслеживающий кости и создающий список капсул, следующих за формой каждого пальца, а в качестве ладони используется сфера. Если рука находится в области действия, то вершинный шейдер обходит список капсул и находит наименьшее расстояние до одной из них, а затем плавно масштабирует колыхания, если капсула пересекает её. Кроме того, перья прижаты к телу. Капсулы имеют увеличенный размер, потому что проверки наложения мягкие, то есть переключаются не резко, а с плавным переходом. Всё это настроено приблизительно так, чтобы когда видимый палец касался пера, оно бы полностью останавливалось и свисало вниз.
Вот тест ранней версии этой системы. Можно увидеть, как перья реагируют на сферу ещё до того, как коснутся её, но взаимодействия всё равно выглядят убедительно.
Для финального релиза игры я хочу создать систему с геометрическим или вычислительным шейдером, которая бы решила часть проблем, возникающих при касании только одной вершины перьев, и устранила бы то, что нормали освещения перьев не изменяются, когда к ним прикасаются.
Информация о ранах сокола
Мы хотели каким-то образом показывать, когда птица ранена, и при этом не использовать полосы здоровья или похожие механики. Чтобы показать, что птица устала или ей больно, используются анимации, но нам по-прежнему не удалось достаточно чётко передать пользователям, что она получила урон. Чтобы явно передать её состояние, мы решили показать на ней физические травмы с кровью и растрёпанными перьями. Очевидным решением стала бы замена материалов. Однако мы хотели показать постепенное увеличение урона, а не просто жёсткое «есть/нет», и не хотели создавать множество различных карт. Также у нас возникла проблема с тем, что большинство перьев использует одинаковые UV-координаты, то есть кровавыми пятнами будет покрыта вся птица.
В результате мы пришли к решению, состоящему из двух частей. Первой было повреждение перьев и растрёпанность. Альфа-канал каждого пера настроен особым образом, чтобы повреждённые и неповреждённые версии находились в альфе с разной непрозрачностью. Для переключения между двумя состояниями перьев используется проверка альфа-значений (по сути это alpha to coverage). 50% непрозрачности обозначают нормальное здоровье, а 25% непрозрачности — раны.
Для пятен крови у птицы есть вторые UV-координаты текстуры крови, поэтому нам не нужно повторно использовать UV-координаты текстуры самого пера. Кровь примешивается поверх базовой текстуры. В результате нам достаточно только одного набора базовых текстур, одного набора текстур крови, и этого хватает для получения разных эффектов ран на птице.
Звуки хищника
Рассказывает Роб Пирсолл.
Мы не хотели, чтобы птица отличалась (например, была футуристичной или магической) от любой другой птицы мира, а просто объединили в ней разные черты нескольких летающих хищников (только добавили ей шляпу). Поэтому не было никакого смысла создавать для неё голос, звучащий «с кинематографическим качеством» — достаточно, чтобы он работал и был правдоподобным.
Иными словами, я мог «позаимствовать» крики любого хищника, которые бы передавали игроку информацию о разном настроении, чувствах и откликах птицы. Я прослушал издаваемые хищниками звуки. К моему удивлению, самый крупный и впечатляющий хищник — орёл — был по звучанию наихудшим из них всех. Он оказался первым в списке «лучше не использовать».
Ястреб — всегда отличный выбор. Все любят клёкот ястреба. Раньше я думал, что у всех звукорежиссёров есть одна запись ястребиного клёкота, и что у всех ястребов во всех фильмах звук одинаков. Но это не так. Как оказалось, это все ястребы звучат одинаково. Почти никаких отличий. Не поймите меня неправильно, звук отличный, поэтому… да, для нашей птицы мы тоже его использовали. Но это ещё не всё.
Лучше всего было то, что я не обязан был ограничиваться одним конкретным видом сокола; а этих видов очень много. Поэтому я мог на свой вкус выбирать любые подходящие звуки, испускаемые любым соколом, которые походили бы на своего рода эмоциональное утверждение птицы.
Очень удобно, что спектр эмоций был ограничен. Я назову их сообщениями птицы:
- Всё тихо, всё хорошо
- Я услышала, что ты меня зовёшь
- Нападаю
- Я ранена, но всё равно лечу
- Больно
Записать звук раздражённого хищника очень просто; достаточно появиться на его территории со звукозаписывающим оборудованием, и он уже будет раздражён. Поэтому есть много материалов, где хищники звучат сердитыми и злыми. Они подходят для звуков «боли». Звуки ястреба подошли для откликов в полёте и сообщений о нападении. Со звуками «всё тихо», возникли сложности. Мне подошло несколько видов щебета, но потом пришлось отредактировать множество разных видов сообщений, чтобы получить частичные, короткие пронзительные крики, соответствующие щебету, и они подошли для игры.
Отслеживание птицы в игре по звуку — это совершенно другая история для ещё одной статьи.