Sumo Digital рассказывают, как они делали систему анимации в Spyder

Перевод статьи от старших программистов Sumo Digital Ника Эдвардса и Энди Чапмана о системе анимации в их игре Spyder.

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

Привет, мы старшие программисты Sumo Digital Ник Эдвардс и Энди Чапман. Sumo Digital периодически проводит внутренние гейм-джемы и дает победителям шанс, что их проект получит развитие относительно текущего концепта. Snake Pass, созданный на Unreal Engine, один из примеров таких победителей, чей проект был запущен в производство, и даже достиг успеха на многих платформах.

Spyder еще одна подобная игра, выигравшая гейм-джем. Оригинальная команда из трех дизайнеров была расширена и начала разработку демо-версии, которая обеспечила этой игре место в Apple Arcade, что означает, что игра сможет работать даже на таких скромных девайсах как iPhone 6. Команда была снова расширена, когда игра начала разрабатываться полноценно. Мы пришли в команду, чтобы переписать существующий прототип Агента 8 на C++, чтобы наладить его с технической части и сделать его более запоминающимся.

В данном материале вы узнаете, как мы достигли этого.

Анимация

Первые шаги

Перед непосредственно разработкой финальной версии нашего протагониста, Агента 8, мы просмотрели ранние итерации персонажа, сделанные для гейм-джема, а также прототип Spyder. Художники и аниматоры хотели сделать паука более выразительным и запоминающимся, что было сложно реализовать с процедурной анимацией, которая была в ранних прототипах.

Немного отойдя от бесчисленных трудностей процедурной анимации. Для персонажа с Х-образными костями нам нужен был скелет с необходимым количеством костей, но их должно быть не слишком много, чтобы на мобильных платформах все это нормально работало. Мы не хотели делать большое количество анимаций, дабы уместиться в рамках бюджета и занимаемой памяти. Так что нам надо было адаптировать тот ограниченный набор анимаций, чтобы они адекватно реагировали на окружение, находясь под полным контролем игрока.

Облачаем Агента 8 в (экзо)скелет

Одним из самых важных требований при работе со стилизованным персонажем является создание скелета для паука, чтобы аниматоры смогли оживить Агента 8. Создание данного скелета было для нас вызовом, так как нам нужно было уложиться в лимит в 75 костей. Это тот край, с которым мобильные платформы могли бы справляться используя лишь GPU. Переходя этот лимит Unreal Engine начинает задействовать CPU для обработки, что приводит к проблемам с производительностью.

К счастью, мы покопались в коде движка и расширили лимит вплоть до 256 костей на ES3.1 платформах, использующих Metal API. Вы можете найти все изменения на GitHub (требуется логин). Так как Spyder выходит в Apple Arcade, мы можем полагаться на все наши платформы, использующие Metal API, и пока отложить эту проблему.

В поисках оптимального пути

Самой трудной задачей в анимации Агента 8 стало его количество ног и то, как они могут взаимодействовать с окружением. В большинстве игр персонаж перемещается лишь в одной плоскости. Перемещаясь вверх и вниз по лестнице, капсула остается вертикальной, и тогда разработчики используют Обратную Кинематику (ОК), чтобы не дать ногам проваливаться под землю.

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

Множество комбинаций геометрии означало, что мы могли бы создать сеты анимаций только для прямых поверхностей под углом 90°. Так что нам нужна была «предугадывающая» ОК, чтобы решать ситуации, такие как пересечение стен на примере ниже, где мы хотели предугадывать движения на другой поверхности и подстраивать анимации соответственно.

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

Пока Агент 8 стоит неподвижно на внешнем углу, рассчитать ОК не так уж и сложно. Проблемы начинаются при движении. Нам нужно было вычислить, куда именно ступит нога, чтобы мы смогли изменить движения по кривым стенам или по краям. В противном случае персонаж бы просто протискивал свои ноги через стену или угол, через который он двигался.

Предугадывающая ОК Агента 8 предвидит, куда ступит нога.
Предугадывающая ОК Агента 8 предвидит, куда ступит нога.

Модификаторы Анимации были использованы на локомотивных анимациях (П.П. locomotion animations), чтобы вычислить и сохранить в составном пространстве (П.П. component space), где шаг начался, а где он окончился. Сначала наши аниматоры создали все анимации с основными движениями, чтобы мы смогли определить движения для всех кадров в анимации. Затем, Модификаторы Анимации отмечают периоды анимации, где нога стоит на земле. Потом, для каждого кадра мы сможем просчитать близкое изменения текущего изменения маршрута и изменение маршрута уже записанных локаций, где нога стояла на земле.

После этого мы размножаем эти близкие изменения на локацию со составным пространством, где нога находится на земле или собирается от нее оттолкнуться, чтобы вычислить финальные значения. Мы разбираем векторы этих локаций на их X, Y и Z компоненты, а затем сохраняем их в разные плавающие кривые в анимации. Три плавающие кривые за каждую принимающую и три за каждую отправляющую локацию (П.П. arrival and departure locations) на каждую ногу, что в итоге дает нам 36 плавающих кривых.

Нужное положение ног закодировано в виде плавающих кривых для каждой ноги и компонента вектора.
Нужное положение ног закодировано в виде плавающих кривых для каждой ноги и компонента вектора.
Благодаря Модификатору Анимации мы смогли сгенерировать принимающие и отправляющие локации для ног.

Вездесущие трассеры

С информацией где ноги будут подниматься и опускаться, предугадывающая ОК сможет работать. Вся логика ОК для нахождения нужных локаций находится в узле AnimGraph. Изначально мы делали это в AnimInstanse, но это вызывало задержки, из-за которых результаты были неточными. Нам нужно было синхронизировать анимации и актуальную информацию с кривой, чтобы мы смогли отбирать, а затем использовать наши трассеры (П.П. traces) и вычисления перед тем, как обновлять Виртуальные Кости, откуда узел LegIK сможет брать информацию. Виртуальные кости служат нам как черновое пространство для изменений, использующееся между разными узлами AnimGraph. В идеале мы бы исключили узел AnimGraph в более используемые секции, чтобы мы смогли видеть Контрольную Установку (П.П. Control Rig) в качестве решения в будущем, когда она будет готова.

Погружаясь в реализацию того, как наш собственный узел AnimGraph использует информацию, мы сначала определили разъем статического референса для каждой ноги в скелете Агента 8, откуда мы уже могли убрать сферические трассеры для отправляющей и прибывающей локации. Они грубо располагались во всех точках таза. С пауком на плоской поверхности, результатом этих трассеров должны были быть их конечные точки. На поверхности близкой к перпендикулярной, результатом трассеров для некоторых ног станет касание поверхности. На поверхности, расположенной близко к краю, результатом трассеров будет то, что нога не будет касаться ничего.

Иллюстрация, показывающая три из множества трассеров, которые мы применяли в определении пространства.
Иллюстрация, показывающая три из множества трассеров, которые мы применяли в определении пространства.

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

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

Перерастяжение — это слишком растянутые в разные стороны ноги.
Перерастяжение — это слишком растянутые в разные стороны ноги.

После «проецирования» (П.П. projecting) нужной локации, куда ступит нога, вместе с поверхностью столкновения мы добавляем дополнительные физические трассеры, чтобы выяснить, находится ли нога на поверхности. Если нет, то мы делаем все заново, чтобы найти следующую поверхность, и затем пытаемся проецировать это все на эту поверхность. Логика нашего проецирования достаточно сложная, чтобы справится с поверхностями с нормальными векторами, но оно хорошо определяет положения ног в случаях, когда Агент 8 касается одной из своих ног поверхностей, которые полностью скрыты от его взора.

Еще хотели мы бы хотели упомянуть, что в большинстве случаев мы удваиваем количество трассеров. Spyder использует два несвязанных комплекса коллизии мешей для большинства объектов и окружения. Первый является более «упрощенным» подходом к рендеру мешей (все еще тройной меш, но с меньшей детализацией). Второй же полностью рендерит все коллизии мешей самостоятельно.

Движение персонажа и системы камеры чаще всего используют упрощенную коллизию, тогда полную использует лишь система анимации. Упрощенная коллизия чаще всего связано с «ходячим» (П.П. walkable) каналом коллизии, тогда как рендер меша остается связан с каналом обзора. Трассеры для ОК используют оба комплекса: упрощенная коллизия больше подходит для выяснения куда нога может ступить, например заклепки или прочие объекты окружения, которые не являются частью коллизии. Более сложная коллизия мешей используются, чтобы убедится, что нога стоит на видимой части геометрии.

Немного о производительности. Изначально мы были скептичны к тому, чтобы делать много трассеров, так как мы сомневались в том, что наши целевые платформы смогут их обработать. Из-за этих опасений, изначально ОК использовала по одному трассеру на ногу на каждый кадр, изменяя цель трассеров, используя AnimNotifies. Мы даже решили использовать трассеры только тогда, когда нужная локация для ноги меняется, чтобы не нагружать трассерами каждый кадр. Но по итогу цена использования трассеров была не настолько высока, как мы думали.

Во время отправной реализации, мы проводили через локацию каждую ногу, отправляясь и готовясь прибыть в каждом кадре для обоих типов коллизии, пока стратегия трассеров не окажется удачной. Как результат: наша система анимации может проводить вплоть до 200 запросов на физику за кадр, когда Агент 8 перемещается по сложной геометрии. При необходимости, мы бы могли оптимизировать это, но поскольку только один персонаж использует этот подход, это не сильно влияет на время кадра.

Искривление движения

Логика нахождения отправления и прибытия ноги преобразовывается, и нам нужно было использовать это, чтобы воздействовать на анимации. Мы подошли к этому с идеей искривить плоскость изначальной анимации в сплайн, который мы создавали используя преобразование. У нас все еще были референсные точки для оправляющей/принимающей позиций в составном пространстве и используя их мы могли выяснить альфа значение для положения между этими двумя позициями.

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

Одинаковый сет для локомотивных анимаций используется вне зависимости от перемещения геометрии.

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

Опознавание поверхности очень важно в выяснении локаций для расположения ног.
Опознавание поверхности очень важно в выяснении локаций для расположения ног.

Движения

Вместе с работой над ногами, мы также тратили время на прокачку и других аспектов анимации персонажа, в частности на отклик других частей тела Агента 8, когда тот двигается.

Антенны

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

Наши аниматоры могли экспериментировать с разными настройками узла, чтобы получить удовлетворительный результат без единой строчки кода. И мы не только заставили антенны двигаться в соответствии с гравитацией, но и получили прикольную дополнительную анимацию, когда Агент 8 ничего не делает. Это добавляет упругости и дополнительной харизмы персонажу, и во время разработки антенны стали чем-то вроде веселых антеннок. (П.П. deely boppers)

Антенны реагируют на положение в пространстве.
Антенны реагируют на положение в пространстве.

Тело

Когда мы придали динамике антеннам и настроили ОК, мы начали думать над тем, чтобы добавить физических реакций телу Агента 8. Все началось с того, что мы захотели повторить эффекты гравитации, чтобы тело паука прогибалось, когда он висит вверх тормашками. Это означало, что нам пришлось изменить превращения основных костей тела, чтобы они могли перемещаться и смещать вращение. В таком случае, без прочих систем, это означало бы, что весь меш, вместе с ногами, смещался. С компонентным пространство ОК это не проблема, так как ноги смогут переориентироваться в зависимости от расположения тела.

После этого мы задумались над добавлением дополнительных эффектов. С самого начала работы над проектом, мы часто обсуждали необходимость перед вес Агента 8. Начиная или заканчивая движение, или находясь на движущейся поверхности, тело должно двигаться по инерции. Чтобы достичь этого мы использовали векторную пружину, выясняя текущее местоположение паука, а затем интерполировали ее на предыдущее положение пружины тела (П.П. body spring location).

Мы применили силу на это положение в некоторых моментах (например при остановке), чтобы повысить покачивание тела. Мы также используем текущее смещение пружины тела, чтобы получить повороты шага и крена, которые в свою очередь, вместе со смещением перевода (П.П. translation offset), которые накапливаются вместе с гравитацией перед тем, как быть примененными на кости тела.

Тело Агента 8 пружинит, что приводит к забавному и динамичному движению.

Гаджеты

Использование гаджетов это один из основных способов Агента 8 взаимодействовать с миром. В игре их несколько и каждый помогает предоставить тактической свободы игроку во время прохождения уровней. Каждый гаджет уникален и по-разному управляется и имеет уникальные анимации. Мы прописывали гаджеты так, что их геймплейные функции были не связаны с анимациями, так что мы имели полный контроль над тем, как они выглядят в действии.

Sumo Digital рассказывают, как они делали систему анимации в Spyder

Каждый гаджет имеет свой класс актера (П.П. actor class), который содержит их физическое представление, где каждый гаджет имеет как минимум два компонента скелетного меша — один для руки, второй для основной части. Скелет руки одинаков для всех гаджетов, тогда как основа уникальна для каждого. Мы пользовались Копированием Позы Из Меша узла AnimGraph, чтобы распространить одинаковые превращения костей от Агента 8 к руке, а от руки к основе. Большинство гаджетов имеют черновые анимации, применяющие разные типы просчитываемой ОК, чтобы получить нужный результат.

Эмоциональный отклик

С полным контролем над анимациями Агента 8, мы хотели сделать его еще более запоминающимся с помощью эмоций. Во время определенных действий в определенных локациях в игре, может сработать эмоциональный триггер, который воспроизведет разные выражения лица во время ходьбы или простоя/беспокойства. У нас есть как минимум одна анимация простоя и беспокойства для каждой из 12 эмоций в игре. Мы проигрываем их в качестве образцов в специальном узле в AnimGraph.

Этот специальный узел что-то вроде узла Случайного Проигрывателя (П.П. Random Sequence Player), но выбирает одну единственную анимацию из списка, зацикливает случайное количество раз на случайной скорости, а затем перестает играть. Это позволяет нам переходить между двумя образцами узла, каждый с собственным набором анимаций, шансами в процентах, временем зацикливания и скорости воспроизведения.

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

Передвижение

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

Проблема

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

  • Никаких пометок или подсказок.
  • Геометрия любых форм и размеров.
  • Двигающиеся поверхности.

Это лишь закрепило тот факт, что из-за сложной и динамичной натуры геометрии уровней, нам нужно как-то распознавать текущее окружения паука в реальном времени

Простые основы

Зная, что нам нужно будет сделать что-то вроде трассировки для того, чтобы определить на каких поверхностях паук сможет перемещаться, мы начали с компонента движения плавающей пешки (П.П. floating pawn) как базы, и затем добавили гравитации и одиночный вызов к трассеру мульти сферы (П.П. multi sphere trace) к нему.

У нас была проблема, когда мы выставляли длину трассера сферы на ноль, движок это замечал и изменял значение на один в оси х IIRC. Мы это обсудили и похоже что это не вызывало никаких проблем.

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

Как только мы попытались использовать один статичный меш, мы столкнулись с одним столкновением от трассера и с недостатком информации.

Пересечения

Следующим нашим шагом было увеличить количество трассеров сферы; один на вертикальную ось паука и четыре следа вокруг: на север, запад, восток и юг относительно паука.

Это сделало наше положение значительно лучше и дало нам в пять раз больше информации. И нам сейчас надо выяснить, что делать с этой информацией.

Летающий Ковер

Мы использовали виртуальную «поверхность движения» (надо было назвать это «летающий ковер», так звучит лучше), которая вычисляется из массива найденных поверхностей, которые мы получили во время трассировки.

Обозначенные поверхности — Серый квадрат отмечает поверхность; красная стрелка показывает, сколько влияния она имеет.
Обозначенные поверхности — Серый квадрат отмечает поверхность; красная стрелка показывает, сколько влияния она имеет.

Мы протестировали список новых поверхностей. Во-первых, отсекая все неподходящие грани (П.П. faces), здесь есть и те, на которых паук не может передвигаться (например над пауком), оставшимся поверхностям мы придали веса за то, как сильно они влияют на ориентацию паука в пространстве, и веса за то, как они должны влиять на положения паука. Мы пробовали разные формулы для вычисления этого веса; последняя формула имела в себе взвешенную сумму из следующих переменных:

  1. Дистанция между локацией удара поверхности и изначального местоположения паука, нормализованных согласно максимальной дистанции просканированной нами, для нахождения поверхности.
  2. Скалярное произведение нормали локации удара и вектора паука, направленого вверх.
  3. Скалярное произведение вектора паука, направленного вперед, и направление места удара для обнаруженной поверхности.

Изначально мы получили кривую, как на картинке ниже:

График, показывающий влияние поверхности на ориентацию паука, уменьшающийся с дистанцией.
График, показывающий влияние поверхности на ориентацию паука, уменьшающийся с дистанцией.

Объединяя вторую и третью переменную, мы получили сложную 3D поверхность, которая позволяла нам смещать вращение паука относительно поверхностей, который для нас были наиболее важными.

Примеры того, как переднее смещение в поверхности влияет на вес.
Примеры того, как переднее смещение в поверхности влияет на вес.

Затем мы использовали контент отсортированного списка, чтобы вычислить локацию и ориентацию виртуальной «поверхности движения».

Виртуальная поверхность движения выделена желтым.
Виртуальная поверхность движения выделена желтым.

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

К этому моменту у нас уже была готова система и пресечения работали хорошо на тестовом уровне. К сожалению, на нашем тестовом уровне не было углов, чтобы мы смогли проверить работу системы на них.

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

Проблема, которую мы назвали «пинг-понг», шла из цикла обратной связи системы ориентации паука, потому что нам нужна была система, которая смогла бы быстро реагировать и ориентировать паука корректно во время перемещения по уровням, и мы не смогли передемпировать (П.П. overly damp) это вращательное движение.

Еще одна проблема пошла из внешних углов, которые были больше 270 градусов, и когда паук шел на большой скорости он мог просто перелететь геометрию и уйти прямиком в неизвестность, словно Койота перехитрил Дорожный бегун.

Очевидной была и проблема, что наш текущий набор трассеров сфер не «видела» скалы, к который ты бы хотел прицепиться, а тебя просто отбрасывает от нее.

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

Массажер головы

Добавив дополнительные трассеры мы решили обе эти проблемы, правда мы не совершили скачок сразу к финальной версии системы, но по итогу это заняло у нас время.

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

Визуализация работы трассеров: красный трассер показывает пересечение с геометрией уровня.
Визуализация работы трассеров: красный трассер показывает пересечение с геометрией уровня.

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

Небольшой рефакторинг кода позволил нам добавлять множество трассеров в массив соединенных векторов, что означало, что мы могли бы более эффективно трассировать кривые, и с небольшими улучшениями в коде мы смогли сделать вращательную дугу (П.П. rotational sweep) каждого трассера на 360 градусов вокруг паука.

Расширение трассеров, слева направо — 1, 4 и 8 трассеров были добавлены.
Расширение трассеров, слева направо — 1, 4 и 8 трассеров были добавлены.

Кэшируем

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

И первопричиной был этот цикл обратной связи:

Sumo Digital рассказывают, как они делали систему анимации в Spyder

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

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

Красная стрелка показывает, где мы сломали цикл:

Sumo Digital рассказывают, как они делали систему анимации в Spyder

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

Это наконец решило проблемы, и приятным побочным эффектом стало то, что мы очень сильно снизили необходимое количества сканирований.

Перейдем к физике

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

Когда пришло время добавить персонажу некоторых движений, опирающихся на физические силы (в угоду геймплея), перед нами встал выбор:

  • Использовать физические силы на главном персонаже и переписать под это код.

Или

  • Симулировать эти силы, чтобы они работали на геймплей.

Мы выбрали последнее.

Главным толчком к принятию данного решения стало то, что мы задумывали проект с пауком в главной роли.

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

И нам не было бы никого толку от этого. Нам нужна была система, которую можно было бы легко настроить и сбалансировать, так что мы выбрали второй вариант.

Рисуем Остатки Совы

Как уже было сказано, нам нужно было добавить немного дополнительных возможностей пауку. Дизайн диктовал нам, что нам нужно было перейти к физическим материалам Unreal Engine, специально для фрикции (П.П. friction), которую мы симулировали.

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

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

Но заставить работать эту систему последовательно через ряд кадров, было не так просто, как мы ожидали. Система работала хорошо на наших тестовых ПК с высоким фреймрейтом. Другое дело — слабые устройства, на которые мы и ориентировались.

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

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

Дальнейшая работа

С выходом Spyder у команды Code появилась возможность порефлексировать над пройденным путем, накопленными знаниями и рассмотреть открытые вопросы.

Если говорить о потенциальной работе в будущем, то на ум приходят две вещи:

  • Сделать паука физическим объектом. Но это больше связано с фреймворком Unreal Engine. Это могло бы дать больше возможностей нашим дизайнером над работой над прототипом и более свободно использовать функционал Unreal Engine.
  • Альтернативное использование технологии липкого передвижения, для создания геймплея в стиле Wipeout, Super Mario Galaxy или Shadow of the Colossus.

Анимация это та область движка, над которой мы бы с интересом поработали дальше. Мы уже упоминали Контрольную Установку, экспериментальную систему, работающую со скриптами, которая была бы хорошим кандидатом для внедрения нашей ОК более модульного и рационального использования. Инерциальное смешивание (П.П. Inertial blending) могло дать нам дополнительную производительность и качество смешивания. Предсказывание Анимации (П.П. Animation Insights) — новый инструмент для изучения игрового процесса и поведения анимации, который выглядит достаточно полезным для разработки. Здесь достаточно инструментов, которое могли бы помочь нам в будущих улучшениях.

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

Ну вот и все.

171171
52 комментария

Призываю @Andrey Apanasik . Все готово, не прошло и двух недель (прошло полторы, а еще я обещал это доделать еще на прошлой неделе, ну да ладно)

8

Надо бы это в /gamedev вывести)

5

Паук из фильма «Дети шпионов» в деле!

8

Комментарий недоступен

4