company_banner

PsRealVehicle, или Open Source-плагин физики танков в Armored Warfare: Assault


    Пару лет назад нашей команде выпала честь заняться созданием мобильной «Арматы». Придерживаясь правила «делаем игру, а не технологию», прототип мы создавали на том, что уже есть в движке. Это был UE 4.9, в основе физической модели — PhysX Vehicles, и много боли (как по поводу, так и без).


    В дальнейшем наша команда создала open source-плагин PsRealVehicle, доступный по MIT лицензии. Этот плагин заточен под физику танков и колесных машинок для высоконагруженных сетевых шутеров, и его работу вы в любой момент можете наблюдать в нашем проекте Armored Warfare: Assault.


    Имена, явки, пароли.


    Четко. Ясно. И только по делу.



    Репозиторий плагина


    Документация по основным конфигам

    Используется в проекте: Armored Warfare: Assault


    Немного истории, или Назад к истокам


    Работу над проектом мы начали на Unreal Engine 4.9. В то время «из коробки» физика машин поддерживала только четырехколесные машинки, а для шестиколесных «лавок» (LAV-400, наша первая «боевая» машина-прототип) пришлось сразу же использовать кастомную сборку движка. Со встроенной физикой танков было ещё хуже: данные о том, как всё работает и настраивается, приходилось по крупицам выуживать из кода.


    Следуя правилу «прототипируй», мы сформировали для себя следующие требования:


    • Физика должна симулировать движение танка (программа-минимум) и колесных машин (весьма желательно — это фишка серии игр AW).
    • Выделенный сервер должен выдерживать до 20 машинок на онлайн-сессию, а клиент должен их обрабатывать.
    • Все колеса и гусеницы должны следовать неровностям поверхности, подвеска должна работать, танк — качаться.
    • Настройка физики должна определяться реальными величинами (масса машинки, мощность двигателя) и вести к реалистичному поведению (возможность преодолевать те или иные виды ландшафта).
    • Чем меньше мы пишем технического кода, тем лучше: движок должны делать Epic Games, а не мы.


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


    1. Всё это весьма бодро жрало процессор.
    2. Создаваемая картина мира никак не хотела укладываться в рамки реалистичного поведения тяжелой техники. Тридцатитонный танк ни при каких настройках не мог взять 15-градусный подъем (а это один из самых легких вариантов). Мы потратили немало времени, возясь с настройками симуляции и трения ландшафта, но это приводило либо к задиранию мощности до космических значений (в 20+ раз больше реальных величин, и в результате машины вели себя нестабильно и непрогнозируемо), либо к игрушечным массам техники (PhysX отлично работает при массе ТС в районе полутора тонн).


    Геймдизайнеры от такого были далеко не в восторге. Программисты плакали, кололись, но продолжали есть кактус (партия требует рабочего решения!). Прототип был одобрен руководством, и отправлен на создание альфа-версии (к слову, видео из прототипа есть на Youtube. Но время шло, а надежды на светлое будущее такой физики становились всё меньше. Настроек было недостаточно, их поведение выглядело чёрной магией. А позиция «игра, а не технологии» по-своему связывала руки. Хотя бы сомнениями в том, а потянем ли.


    Тихонько вооружившись Википедией, остаточными школьными знаниями и опытом работы над физикой «на понтонах» а-ля Assassin's Creed, за пару дней я создал прототип новой физики танка, который и лег в основу плагина PsRealVehicle. В течение недели proof-of-concept был поставлен на ноги, показан CTO команды и защищён нагрузочным тестированием. Цифры говорили: своей физике — быть.


    ...-..., и в продакшн


    Путь от прототипа до прода вышел куда длиннее. Если на концептуальную проверку хватило недели, то на адекватную бета-версию ушло уже месяца полтора. Создание полноценного «продовского» релиза заняло около полугода, постоянная доводка и коррекция — на протяжении всего времени работы над проектом. Во многом такой высокой скоростью разработки и внедрения физики в проект мы обязаны пришедшему как раз в то время в нашу команду техническому геймдизайнеру Игорю, чья дотошность в аспектах работы математической модели и ее субъективного восприятия игроками и привела к текущему результату. Должен признать, в технологическом смысле я — варвар: мое дело сделать топор, чтобы валить лес. После обработки Игорем и доводки модели другими ребятами мы получили production-ready открытое решение, масштабируемое и в высшей мере оптимизированное для нужд мультиплеера. Здесь есть чем гордиться: из множества доступных на рынке плагинов (включая встроенный PhysX Vehicles) наш самый быстрый и прозрачный в настройке.


    Кстати, не обошлось и без смешных случаев. Пока мы работали с PhysX Vehicle и наши предельно скользкие многоколесные машинки не могли взобраться на мелкие холмы, я не раз слышал упреки, мол, не может наша команда настроить, чтобы как у людей было. Решение об использовании своего плагина было принято, в том числе, под влиянием этого кадра:



    Новейшая разработка советской армии! Танк-паук, который способен подниматься на 89-градусные стены. Такое крыть было просто нечем :D


    Особенности нашего решения


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



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


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



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



    Структура танка в AW: Assault


    Иерархия классов


    AAwmVehicle — главный C++ класс, отвечающий за машинку в игре, разбитый на множество компонентов (движение — UPsRealVehicleMovementComponent, звуки, VFX, статистика, броня и другие). От него наследуется блюпринт BP_DefaultVehicle, который является дополнительной прослойкой для настроек по-умолчанию для всех машин. Все прочие — частные блюпринты настроек для каждой единицы техники в игре.


    Каждая машина представляет из себя набор таких данных:


    • Блюпринт, где прописаны все внешние ассеты, заданы звуки, свойства а-ля «колесная/гусеничная техника», и настроена физика.
    • Скелетал меш и привязанные к нему ассеты:
      — Физический ассет (здесь никакой магии, всё стандартно).
      — Анимационное дерево.
    • Текстуры (diffuse, normal map, RMM).
    • Материал инстансы (корпус, гусеницы + разрушенное состояние).
    • Набор мешей брони для системы пробитий.
    • Камеры, чекеры уровня воды и прочие вспомогательные коллизии.

    Анимация танка


    Настроить один танк — мелочь, каким бы сложным ни было анимационное дерево. Настроить десятки таких танков и поддерживать их в актуальном состоянии, при изменении костей, меша и так далее — совершенно неадекватный объем для ручной работы. К счастью, в нашем случае речь идёт о достаточно стандартизированном «персонаже»: танк можно препарировать на сущности и называть их шаблонно. Речь, конечно же, об именовании костей.


    Такой подход позволил использовать по сути одно и то же анимационное дерево, которое святыми Ctrl+C / Ctrl+V множится на любое число танков и не требует никакой поддержки, кроме изначального QA-check'а.



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


    Материалы танка


    Для всех частей танка используется один мастер-материал, кастомизируемый парой Switch-нод.



    Далее мы получаем такое дерево:


     - M_Vehicles
     - -- MI_Vehicles_Clean_Body
     - -- -- MI_Leopard2
     - -- -- -- MI_Leopard2_LOD
     - -- MI_Vehicles_Clean_Treads (стоит галочка "Treads")
     - -- -- MI_Leopard2_Treads
     - -- -- -- MI_Leopard2_Treads_LOD

    Настоящий «вес» здесь имеют только M_Vehicles и MI_Vehicles_Clean_Treads, все остальные инстансы — просто наборы параметров и потребляют минимум памяти и места на диске.



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


    Работа брони


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



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


    Самое удобное для такого случая — читать «голые» данные меша, которые для выделенного сервера мы не strip'аем.


    Сеть и экстра-оптимизация


    Пара «околотанковых» моментов, которые я также хотел бы кратко упомянуть.


    • Всё движение танков осуществляется только на сервере, клиенты лишь интерполируют полученные значения. Никакой экстраполяции не используется. Частота синхронизации — 10 раз в секунду.


    • В зависимости от ScreenSize танка мы пропускаем то или иное количество тиков скелетал меша, что включает в себя обсчёт всех анимаций и некоторых физических взаимодействий. Если танк не виден на экране — он тупой не анимированный ящик, плавающий в пространстве. Встроенный Update Rate Optimization, несмотря на хорошую идею, обладает весьма грубой реализацией, не дающей ощутимого прироста производительности. Особенно, если речь о мобилках.


    • Для всех танков, кроме собственного, на клиенте отрезаются все компоненты, кроме самых базовых: камер, чекеров и прочего, из чего состоит танк. По сути, они не имеют ничего, кроме внешнего вида.




    • На выделенном сервере ездит форсированный LOD1 танка. Меньше вершин — меньше потребления процессора. Причём обновление положения кастомных кусков брони происходит только в момент попадания прожектайла: нет смысла обновлять состояние частей каждый тик.

    Me, Myself & Tanks


    Мы в Pushkin Studio считаем, что обмен опытом разработки очень важен, в том числе и для роста профессионального уровня внутри команды. Open Source-проекты — значимая составляющая такого подхода, и я рад, что могу представить сообществу такую технологию, как PsRealVehicle.


    На мой взгляд, очень важно, что мы сами ежедневно используем все публикуемые нами плагины и утилиты. Ведь путь, ярко демонстрируемый самими Epic Games, заключается в том, что успех хорошей технологии — это использование её самими разработчиками в собственных продуктах. Сейчас мы работаем уже на версии UE 4.20, наш плагин прошел с нами весь этот путь, и мы не собираемся останавливаться!


    • +34
    • 2,9k
    • 7

    Mail.Ru Group

    870,33

    Строим Интернет

    Поделиться публикацией

    Похожие публикации

    Комментарии 7
      0
      Здравствуйте!

      Спасибо за интересную статью!

      У меня есть к Вам пара вопросов:
      1. Каким образом плагин взаимодействует с Physx? Правильно ли я понимаю, что в результате работы изменяются положения отдельных объектов, а остальные расчёты отдаются на откуп Physx?
      2. Относительно копирования анимационных деревьев для танков: существует ли какой-либо альтернативный способ?
        0
        1. На самом деле мы работаем полностью в рамках PhysX: плагин высчитывает какую силу и куда приложить к телу танка, в зависимости от текущего его состояния. Как раз именно просчётом перемещения занимается уже сам PhysX.

        2. Анимационное дерево как таковое должно быть (именно оно управляет анимацией), но в теории можно свести к пустому дереву, создав кастомный класс-наследник AnimInstance и прописав всю логику в коде. Но мы такого не делали, вероятно могут возникнуть сложности :)
        0

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

          0

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

            0
            Очень рад, спасибо! ;)
            0

            Чем плагин отличается от этого готового плагина https://github.com/BoredEngineer/MMT_Plugin
            Давно жду в игре реалистичных повреждений композитной брони от трещин до полного разллета брони, а также вмятин на мягких участков танка от попадания снарядов.

              0
              Другая физическая модель, другая архитектура. Мы не ставили задачи создать «компонент широкого пользования для физических моделек», у нас вполне себе выверенное решение конкретных целей, с кучей шишек, набитых продом :)

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

            Самое читаемое