Оптимизация физики в многопользовательской игре — опыт разработчиков Shadow Fight Arena

Плоская иерархия и XPBD.

Ведущий технический художник Banzai Games Роман Терский в колонке для DTF рассказывает, как команда оптимизировала и улучшала физику в мобильном файтинге Shadow Fight Arena. Разработчикам было важно добиться не только реалистичности и кинематографичности, но и согласованности движений персонажей на разных устройствах при синхронном PvP.

Визуально Shadow Fight Arena (SFA) выгодно выделяется среди других игр серии благодаря переходу на Physically Based Rendering (PBR). Мы значительно улучшили графику, повысив качество текстур, изменив освещение и добавив пост-эффекты.

Чтобы соответствовать установленной планке, мы также переработали физику в игре, улучшив её как визуально, так и в плане оптимизации. В предыдущей статье я рассказывал о технических решениях, которые мы применили при настройке реалистичной и оптимизированной физики в игре Shadow Fight 3 (SF3). Часть этих решений перекочевали в SFA, поэтому я буду периодически ссылаться на старую статью. Однако большинство этих решений были изменены или улучшены.

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

Плоская иерархия

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

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

Оптимизация физики в многопользовательской игре — опыт разработчиков Shadow Fight Arena

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

Как же переход на плоскую иерархию сказался на физике?

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

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

Во время последнего кадра анимации происходила синхронизация трансформов костей двух скелетов. Физический клон считывал положение и ротацию костей основного скелета и задавал своим точно такие же параметры.

Затем активировался rigidbody, и кости физического клона подвергались симуляции. Далее, вплоть до начала следующей атакующей анимации, уже основной скелет каждый кадр считывал трансформы костей физического клона, которые в этот момент двигались по физике, и задавал эти параметры своим костям.

Физический клон отлично показал себя в плане реалистичности поведения во время симуляции, но, к сожалению, такое решение не лучшее с точки зрения оптимизации, так как кости в иерархии в связке с джоинтами требуют лишних вычислений. Гораздо «дешевле» связывать джоинтами кости, являющиеся отдельными game object.

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

Во-вторых, мы отказались от фейкового импульса, который применялся в SF3 для исправления визуальных артефактов при симуляции физики твёрдых тел. В SFA использование этого решения невозможно, так как оно подразумевает нахождение симулируемых костей внутри иерархии. Однако фейковый импульс — скорее временная мера и не даёт достаточного физически реалистичного результата, и для SFA мы применили другой метод.

Для начала о проблеме. При стабильных 60 FPS все идёт гладко, но во время просадок, которые возможны на слабых устройствах, мы наблюдаем следующее: симулируемые кости начинают с задержкой «догонять» анимируемые кости, с которыми они связаны джоинтами.

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

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

Оптимизация физики в многопользовательской игре — опыт разработчиков Shadow Fight Arena

В качестве решения мы отключили автоматическое обновление физики в Unity. Теперь мы самостоятельно обновляем физическое состояние объектов после основного апдейта и перед рендером. Это решение было бы невозможным, если бы мы использовали дефолтную физику Unity для персонажей. В таком случае симуляция для них развивалась бы по-разному в момент просадки FPS на одном из устройств, что непозволительно при синхронном PvP.

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

Оптимизация физики в многопользовательской игре — опыт разработчиков Shadow Fight Arena

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

XPBD-детерминированная физика, построенная на твёрдых телах

Персонажи в серии игр Shadow Fight подвергались нескольким итерациям настройки физики. В SF3 мы использовали дефолтную физику Unity до тех пор, пока в игру не был введён режим синхронного PvP, для которого потребовалась одинаковая симуляция на двух клиентах. Из-за вычислений с плавающей запятой, которые используются внутри физики в Unity, от неё пришлось отказаться в пользу собственной физики, построенной на узлах, мышцах и ребрах и использующей целочисленные вычисления.

В Shadow Fight Arena мы пошли дальше и, основываясь на предыдущем опыте, создали новый ragdoll для персонажей, основанный на подходе Extended position-based dynamics (XPBD). Новая физика также использует целочисленные вычисления и полностью детерминированна, однако имеет ряд преимуществ перед предыдущем решением, построенным на узлах.

Оптимизация физики в многопользовательской игре — опыт разработчиков Shadow Fight Arena

С технической точки зрения традиционная Unity-физика имеет constraint solver, а XPBD-физика — iterative solver. То есть вместо того, чтобы решать каждый тик систему уравнений для выяснения того, какое положение тел удовлетворит всем ограничениям, мы итерационно выводим систему из состояния с нарушенными ограничениями в состояние, соответствующее им.

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

В методе PBD, когда обнаруживается проникновение двух объектов, положение объекта напрямую корректируется в соответствии с заданными ограничениями, а затем обновляется информация о скорости. Итеративный метод PBD обеспечивает сравнимое с PhysX качество удовлетворения ограничений за счёт большего количества итераций. Благодаря этому PBD даёт больше детализации без потери очень быстрых движений и контактов, однако существенно хуже масштабируется по сравнению с PhysX. Поскольку в нашей игре одновременно могут быть активны только два ragdoll, нас это полностью устроило.

Наш ragdoll состоит из box-коллайдеров, соединённых между собой джоинтами двух типов: Spherical и Hinge. Первый тип ограничивает поворот коллайдеров по заданным осям, а во втором указывается конус вращения по определенной оси. Для этих box-коллайдеров рассчитываются столкновения только с бесконечным горизонтальным полом, соответственно они не имеют коллизий между собой и с внешними динамическими коллайдерами. Таким образом, на результат симуляции влияет только стартовая позиция.

Избежать вероятности проникновения тел друг в друга нам удалось за счёт точечной настройки каждого джоинта. Также для каждого тела настраивается масса, а для соединений — степень затухания (damping) и другие стандартные для подобной системы параметры.

Оптимизация физики в многопользовательской игре — опыт разработчиков Shadow Fight Arena

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

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

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

Нам хотелось добиться эффекта сгруппированности, как если бы персонаж был просто сбит с ног, но сохранял сознание. Для этого мы добавили ещё одно ограничение для box-коллайдеров — стремление к определённой позе. В результате мы получили сгруппированное, но очень жёсткое тело, поведение персонажа стало слишком «деревянным».

Для достижения более мягкой симуляции мы добавили регулируемый параметр податливости (Compliance) и сделали его динамическим. Первые 20 кадров симуляции мы повышаем значение Compliance, делая тело более мягким в момент получения удара и перехода в физику.

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

Original — Pose — Pose + Compliance

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

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

Помимо этого мы всегда придаем дополнительный импульс в размере 20% от основного по оси Z, слегка подкидывая ragdoll. А в случае если во время симуляции персонаж получит новый удар, мы сохраняем изначальный вектор движения, добавляя к нему только 30% от нового импульса. Все эти манипуляции позволили добиться достаточно реалистичного и кинематографичного результата.

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

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

Подробнее ознакомиться с методом Position based dynamics можно по ссылке. А демо и сорсы доступны для скачивания тут.

146146
32 комментария

Какой же все таки у них охрененный риггинг движения и тела

22
Ответить

хе-х, зато Юнити запилили новую заставку логотипчика

1
Ответить

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

13
Ответить

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

5
Ответить

У нас свой анимационный движок, который знает про иерархию, но эта информация уже не нужна, когда посчитанная поза переносится на сцену в Unity. Т.е. иерархии нет именно на трансформах, но во внутреннем представлении она есть.

9
Ответить

Анимацию можно сохранить и на плоский скелет, просто она весить будет в 5-10 раз больше.

Оптимальное решение делать только ключевые кости плоскими.

1
Ответить