Pull to refresh

Comments 14

Спасибо за статью. Можете поделиться, какой 3D движок выбрали?
Будет отдельная статья, в которой подробно расскажем как переходили с 2D физики на 3D, но забегая вперед могу сказать, что взяли bepuphysics2 (https://github.com/bepu/bepuphysics2).
Спросил в надежде — может используете что-нибудь от Unity, нативно на клиенте и сервере, может что-нибудь уже можно применять для мультиплеера от них. Я пробовал BulletSharp, он недетерменированный, но это все решается (синхронизируется) — при компиляции из плюсов под нужную платформу можно убрать кучу ненужного функционала: ткани, канаты, сложные джоинты и т.д.

Для 2d мы пробовали Volatile — только из-за хранения истории его использовать смысла нет, это дело второстепенное; пробовали нативно Box2d — на iOS были большие проблемы с производительностью; по итогу написали свой, с применением ECS подхода — детерминированно, но простенько — без джоинтов, только коллизии, сенсоры и рейкасты.
Не рассматривали физику Unity ни в каком виде, т.к. на сервере у нас нет Unity. При выборе движка смотрели в сторону и BulletSharp и Box2D, но были опасения насчет нативной части — не хотелось тратить время на рандомные нативные краши и поиск ошибок в коде огромной библиотеки, вместо того, чтобы сосредоточиться на разработке продуктовой логики, что очень важно на начальном этапе проекта. Опять же дописывать историю в либах, борясь с их внутренними кешами тоже то ещё удовольствие. Мы взяли Volatile и не прогадали. В результате отсутствия Unity на сервере наши серверы справляются с довольно внушительными нагрузками, библиотеке не требуется поддержка — это значит, что всё сэкономленное время мы можем вложить непосредственно в игру.

А вообще, если стоит вопрос о Unity решении я бы начал смотреть в сторону ещё превьюшного Unity.Physics: docs.unity3d.com/Packages/com.unity.physics@0.0/manual/design.html
Тут важно понимать, что решения по ECS и физике мы принимали задолго до того, как Unity решила пойти в ногу со временем.

Вообще при переходе от 2D к 3D рассматривали даже такой радикальный шаг как запуск сервера на Unity, и как следствие использование Unity физики или на худой конец использование той же версии PhysX на сервере, что и на клиенте. Но остановились на более экстравагантном варианте. В следующей статье подробно расскажем про него — там будет очень интересно.

Опять же забегая вперед могу проспойлерить, что не обязательно крутить ту же самую физику на клиенте и сервере — она всё равно недетерминированная, так зачем мучиться? =)

А про опыт написания даже простенькой физической либы в стиле ECS я бы с удовольствием почитал — пишите статью!
или на худой конец использование той же версии PhysX на сервере, что и на клиенте

Конкретно на этот вариант и надеялся. Я подумывал поэкспериментировать с этим, но пока только мысли — надеялся что у вас что-то подобное, когда спрашивал.

рандомные нативные краши

Да, этого крайне много в том же BulletSharp и на исправление уходит тонна времени.

Не рассматривали физику Unity ни в каком виде, т.к. на сервере у нас нет Unity.

Да, такой вариант разве что для прототипов может подойти, там много лишнего получается — хотя сейчас можно настраивать PlayerLoop (ScriptBehaviourUpdateOrder.UpdatePlayerLoop), экспериментальная штука, но все равно много лишнего.

она всё равно недетерминированная, так зачем мучиться? =)

Тут надо смотреть как быстро накапливается ошибка, насколько частые откаты. В случае детерминизма откаты будут во многом из-за получения станов, замедлений. В случае недетерминизма откаты будут чаще — соответственно больше затраты процессора на ресимуляцию, затраты по сути в самой затратной системе. Жаль Вы про это в статье не написали, буду ждать продолжение.
Да, такой вариант разве что для прототипов может подойти
У нас Unity инстансы на сервере вполне нормально работали в MOBA игре.
Тут всё зависит от подхода. Крутить Unity на серверах это просто очень дорого и не стабильно. Учитывая, что создание обычного .net сервера стоит нам как минимум тех же усилий, что борьба с Unity (не забудьте про кручение физики, pathfinding, которые надо закостылить, чтобы запускать много матчей в рамках одного процесса Unity; невозможность Unity работать со стандартными серверными либами вроде RabbitMQ, утечки и плохая утилизация многопоточности и современной .net среды), а в выигрыше будет хорошая утилизация серверного железа и как следствие — косты, то мы решили особо не мудрить.

Но тут стоит отдать должное Unity — они отлично понимают, что серверный кейс Unity существует и активно работают над поддержкой этого направления.
Да, дороговато. У нас там было по одному инстансу на ядро. В каждом инстансе 10 комнат на 6 человек (если речь про арены) или 100 комнат на планеты (если речь про деревню игрока, где ситибилдинг часть). В итоге одна машина с 4 ядрами держала 200-300 ccu.
Тут надо смотреть как быстро накапливается ошибка, насколько частые откаты. В случае детерминизма откаты будут во многом из-за получения станов, замедлений. В случае недетерминизма откаты будут чаще — соответственно больше затраты процессора на ресимуляцию, затраты по сути в самой затратной системе. Жаль Вы про это в статье не написали, буду ждать продолжение.


К сожалению, детерминизм как раз не решает описанных вами проблем — станлоки по прежнему будут отбрасывать предикшн игрока назад. Фактически основной селлинг поинт детерминизма — это экономия траффика, т.к. в этом случае с сервера перестают слаться снапшоты и шлются только инпуты потому что клиент, при наличии детерминированной симуляции, может полностью локально восстановить состояние мира. В этом случае количество ресимуляций в среднем будет как раз больше, т.к. с детерминизмом и наличием только инпутов откатывать состояние мира нужно постоянно как минимум на размер пинга, или больше, чтобы учесть в состоянии ввод других игроков. Посмотрите приложенную к статье лекцию от NRS. Там ресимуляции происходят постоянно и под них в Injustice и MK11 заложен кусок времени фрейма.
Посмотрел видео, довольно интересно.

Но видео рассказывает о Peer to Peer, где каждый клиент обязан симулировать всю физику (до конца так и не понял как они частицы симулируют). У нас простая интерполяция, мы других игроков двигаем не при помощи физики, зачем нам их инпут? У них понятно почему инпут, у них до этой модели вообще как я понял был локстеп, каждый клиент поддерживает симуляцию, у него нет сервера, который поможет. Если другие игроки взаимодействуют с миром — игрок не может это знать, будет рассинхрон — но это будет рассинхрон не из-за ошибки вычислений.
В том-то и дело, что когда есть детерминизм, то трафик становится копеечным — в этом его основной селлинг поинт. И серверы становятся не нужными, т.к. каждый клиент в состоянии пересчитать состояние всего мира самостоятельно. Фактически сервер может вообще проводить валидацию боёв постфактум и банить читеров постфактум. И более того, затраты кадра на ресимуляцию всегда фиксированы и заранее заложены в кадр, по этому не зависят от случайных миспредиктов и как следствие не порождают спайков FPS.

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

Если же говорить о детерминизме в нашей схеме — она помогает с расхождениями, да, но тут же возникает соблазн сделать всё вышеописанное, т.к. это реальная экономия ресурсов (если мы конечно говорим о более-менее крупных проектах).
Большое спасибо за ответ, теперь я Вас понял.

У нас был прототип — но делали не на Unity — использовали Unreal. Суть в том, что есть 2d мир и помимо твердых тел есть упругие тела, флюиды (только жидкости если точнее) и ткани (cloth) — физика таких тел представлена частицами (использовали LiquidFun). Что-то похожее на Terraria планировали, выживалку. По итогу физика была ядром механики и очень много съедала времени — довольно много чего испробовали — слать снапшоты было вообще не вариант. Пробовали локстепом сделать и передавать только инпут, пробовали как-то вычислительные шейдеры подключить — но по итогу так и не нашли способ.
Локстеп с инпутами и детерминизмом подходит только для игр с низким тикрейтом (10Гц или меньше), так как требует гарантии доставки инпута (rudp), обычно используется в стратегиях и моба. Снапшоты и инпуты используют в динамичных играх/шутерах, где негарантированную доставку снапшота можно игнорировать (может быть интерполирован с прошлым) и важна больше скорость доставки. Для уменьшения размера снапшота используют делта компрессию и компрессию таблицы изменений
Плюсую верхний коммент про статью о физике на ECS :3
И не опенсорсная ли она у вас?
Sign up to leave a comment.