Comments 77
А далее разные игры обрабатывают такие ситуации по разному:
- Оба игрока умирают(т.к. оба игрока совершили выстрел пока еще были живы и оба попали в своего врага).
- Игрок, команда которого дошла до сервера первой, остается вживых. Т.е. когда команда на выстрел доходит до сервера, сначала сервер проверяет, жив ли игрок в данный момент времени, и только если жив проводит рейкаст в прошлом.
В CS:GO выстрел настигает жертву мгновенно
В Overwatch почти у всех персонажей есть скорость полета «пули», кроме Трейсер, DV-a Солдата-76 и похоже Вдовы. Выстрелам остальных героев требуется время, чтобы добраться до конечной точки координат.
Вы живы, вы выстрелили, пуля полетела, соперник жив.
Соперник жив, соперник выстрелил, пуля полетела, вы тоже живы.
Тут «пули» долетают до целей и оба погибают.
Вместо полета пули выполняется один рейкаст, как бы предполагая что скорость пули бесконечна.
Т.к. они и так не мгновенно летят, а значит каждый человек допускает возможность того, что он промахнулся)
Так как на клиенте мы используем интерполяцию для отображения позиций врагов, было бы не вполне корректно применять конкретное состояние сервера, которое якобы отрисовывал клиент, ведь на самом деле игрок стрелял во врага, который находился между двумя какими-то состояниями.
Раз уж мы применяем механизм компенсации лага, с его помощью можно найти два состояния мира, между которыми произошел выстрел и проинтерполировать их.
Получается, сервер должен тоже интерполировать, между двумя последними кадрами, переданными игроку?
Так как сервер все равно рассылает свое состояние каждый кадр по клиентам, он может восстановить любой момент из прошлого. В том числе, он может восстановить мир в точности таким, каким его видел клиент в момент выстрела.
А вот интересно, при довольно сложном мире, где много объектов, которые могут на что-то влиять, как это осуществляют? Меняют ли состояние всех объектов? Или как-то выбирают те, которые могут влиять?
А вот интересно, при довольно сложном мире, где много объектов, которые могут на что-то влиять, как это осуществляют? Меняют ли состояние всех объектов? Или как-то выбирают те, которые могут влиять?
Очевидно, ответ зависит от конкретной ситуации. Если у вас шутер с комнатами по 15 человек и меняются только свойства игроков, можно смело откатывать весь мир.
Если у вас MMO с интерактивным миром, стоит откатить только небольшое окружение игрока.
Откатывать тоже просто — просто применять по очереди все изменения мира.
Для тех, кто первый раз слышит о дельте — это разность двух состояний.
К примеру, есть состояние А, в котором у игрока П1 100хп, у игрока П2 — 80хп. И вот игрок П2 наносит урон игроку П1 в размере 30единиц.
Теперь состояние мира Б выглядит так:
П1 — 70хп
П2 — 80хп
Дельта двух состояний:
П1 -30хп
Можно отправить состояние Б с данными:
П1 — 70хп
П2 — 80хп
Или отправить дельту А и Б:
П1 -30хп
Тут следует уточнить, что дельту можно применить только к «правдимому» состоянию, т. е. игрок, получивший дельту, знает точное состояние мира до прихода дельты, чтобы новое состояние было согласовано с сервером. Хотя для данных, которые не важны, можно пожертвовать совпадением с сервером.
Для огромных миров, например как майнкрафт, это экономит огромное количество трафика (там еще всякие чанки и компрессии)
Пусть изначальное состояние
X = 0.
Delta 0
X += 1
Delta 1
X -= 1
Delta 2
X += 1
Если, например, Delta1 не дойдет до клиента, у него X будет всегда на единицу больше чем надо.
Значит надо чтобы все дельты дошли. Так как UDP не гарантирует доставки пакетов, а использовать TCP — самоубийство, надо строить reliable протокол над UDP.
Может быть такая ситуация. Стрелок целится в голову жертвы по версии стрелка. По версии жертвы она успела уйти в сторону. Как будет разруливаться такая ситуация? Тот кто раньше сообщил свое состояние (малый пинг) тот и полбедил?
Что значит «Интерполирует предыдущие состояния других игроков»? Клиент получает положение и вектора других игроков и расчитывает новое положение?
Интерполяция — это значит, что клиент, условно говоря, передвигает врага между двумя устаревшими кадрами.
Прочитайте предыдущую часть для более подробного объяснения.
Может быть такая ситуация. Стрелок целится в голову жертвы по версии стрелка. По версии жертвы она успела уйти в сторону. Как будет разруливаться такая ситуация? Тот кто раньше сообщил свое состояние (малый пинг) тот и полбедил?
Прочитайте и первую часть тоже. Сервер авторитарный. Что говорит сервер — то и правда.
Сервер для определения попадания откатывает время назад, так что если стрелок с точки зрения его клиента попал, он скорее всего попадет.
Это все чисто предположения, но да: по хорошему нужен судья который будет не только откатывать/интерполировать, но и учитывать текущие пинги обоих игроков
Интерполяция — это нахождение промежуточного положения между двумя крайними точками, так что она тут никак не поможет.
А экстраполяция не применяется в шутерах для положений персонажей.
Прочитайте предыдущую часть для более подробного объяснения.
Интересно, какие еще есть приемы для повышения играбельности при высокой и нестабильной задержке.
И как будет вести себя сервер, если таких читеров не один и не два, а полсервера? Какие причудливые бои будут разворачиваться.
Вы успеете понять что надо делать по команде вашего друга за полсекунды? А ведь ваш друг еще должен тратить свой самый ценный ресурс — внимание на то чтобы следить за происходящим вокруг вас. На закуску. Скорость реакции среднего человека на внезапное событие 250 мс. Можете проверить вашу скорость реакции вот тут. Таким образом пока ваш друг отреагирует на событие + пока вы отреагируете на сообщение друга, пройдет в лучшем случае 500 мс. Знакомое число? И это мы считаем, что друг вас уколол иголкой, а не словами сказал.
А еще с пингом 500 играть банально не удобно. Обычно если два игрока отправляют команды на убийства друг друга, в живых остается тот, чья команда дошла до сервера быстрее.
> Обычно если два игрока отправляют команды на убийства друг друга, в живых остается тот, чья команда дошла до сервера быстрее.
Разве? Давайте посчитаем. Пусть Семён играет с реальным лагом в 1 секунду и виртуальным лагом в 5 секунд, а Иван с настоящим лагом в 1 секунду. Петя помогает семёну и тоже имеет лаг в 1 секунду. На 2 секунде Иван атакует Семёна, на третьей секунде команда семёна дошла до сервера и сервер «убил» Семёна. На четвёртой секунде об этом узнал Петя и немедленно уведомил об этом Семёна. Тот тут же послал сигнал «убить Ивана», который дошёл до сервера на 5 секунде. Сервер вычел эмулируемый лаг в 5 секунд и посчитал, что семён стрелял на нулевой секунде, а значит успел первым. Семён оживает, Иван умирает.
Если игрок убит, он не будет воскрешен даже если выяснится, что его убийцу «убили» раньше.
А если рассматривать программные хаки, так гораздо удобнее для реализации предоставленных уязвимостей, скажем, отображать всех врагов вне зависимости от того, видны ли они. Все равно эта информация скорее всего доходит до клиента.
Или классический AutoAim, который по зажатию кнопки будет целиться в голову врага.
А это не имеет никакого отношения к механизму лагокомпенсации:)
То есть реальность отличается от изложенной в статье теории? Но допустим, но ведь это нечестно. Для настоящих лагающих, а не фейкающих.
Сервер оставляет стрелка в том положении, в котором он находится; а весь остальной мир меняет на то состояние, которое клиент отображал в момент выстрела, т.е. возвращает назад во времени.
Сервер обрабатывает выстрел и получает его результат.
Сервер возвращает весь мир в текущее состояние времени.
Сервер применяет результат выстрела и рассылает обновления по клиентам как обычно.
Т.е. сервер применяет результат выстрела уже в настоящем времени.
Да, это не честно по отношению к лагающим, но компенсация лага не для честности существует, а для того чтобы лагающие вообще могли играть и вешать хэдшоты.
Если хотите, можете применять выстрелы в прошлом, флаг вам в руки разбираться с применением ввода остальных игроков, потому что там нехилые временные парадоксы возникнуть могут. И иногда получаются настоящие петли времени, из которых не очень понятно как выходить.
Это значит, что сервер округляет положение игроков и если траектория более-менее попадает под округления — зачет

Естественно, я не говорю про спрей, когда выпускается вся обойма
Как применимы ли ваши алгоритмы к компенсации скорости передвижения?
Давайте представим ситуацию, когда выстрел не убивает. Первый игрок стреляет и попадает. У второго брызжет кровь, выпадает из рук оружие и он прихрамывая бежит дальше. Допустим, второй игрок в своем времени убежал на полсекунды от места столкновения. Кровь и снаряжение остались позади. Но он не убит (допустим был в шлеме), а его физические характеристики должны были измениться. Спрашивается, с какого момента? Раненный он не мог бежать с той же скоростью и за полсекунды пробегает уже меньше.
Допустим, это не выстрел, а удар в рукопашной с последующей анимацией броска через спину с прогиба. Второго игрока надо телепортировать? «Эй, парень, ты тут уже полсекунды на земле лежишь, нажми кнопку встать!»
Второй игрок имеет щит, которым может на 400мс прикрываться от летящих в него пуль с кулдауном 400мс. Пинг первого 500мс, второго — 0. Что делать?
В общем, каковы ограничения физической модели игры и каковы ограничения отката времени?
Пусть есть игроки A, B и C. А выстрелил в B, но у него большой пинг. B выстрелил в C, его сигнал мгновенно дошел и игрок C умер, что и отобразилось на клиенте. Потом дошел сигнал от A, игрок B умер в прошлом, а значит C ожил. Выглядит как странный лаг.
Допустим, это не выстрел, а удар в рукопашной с последующей анимацией броска через спину с прогиба. Второго игрока надо телепортировать? «Эй, парень, ты тут уже полсекунды на земле лежишь, нажми кнопку встать!»
Поэтому обычно такое мощное взаимодействие не делают)
Глобально правила для многопользовательских игр такие: на один физически объект(положение и вращение) единовременно может влиять не более 1 игрока.
В противном случае пинг от 50 ощущается просто отвратительно сильно.
В целом мнения расходятся, однако часто пишут, что во множественном, особенно в разговорной речи вполне нормально через О
Смутило только что такой вариант, возможно, пошел из тюремного жаргона.
Так большой пинг несомненно является читом.
Позже подобный тип мультиплеера пришел в ватч догс и мгс 5.
Ну мультиплееры во всей серии Souls похожи. В целом, там всё тоже самое: если попадается игрок с большим пингом, то часто по тебе проходят удары, которые с твоей точки зрения не должны были до тебя достать, так как ты вышел из зоны действия оружия. Или удар в спину: ты уже стоишь лицом, но тут тебя телепортирюет к позиции врага и срабатывает анимация удара в спину.
Интересно вот что: там многие игровые значения рассчитываются исходя из FPS. Иногда это выглядит забавно, например, оружие при 60 FPS изнашивается куда быстрее, чем при 30. Вы не знаете, зачем так делается, какие плюсы и минусы у такого подхода и т.д.? Интересно было бы почитать.
Все обычно наоборот стараются абстрагироваться от FPS. А чтобы привязывали износ к FPS — это знатный изврат)
На тему рукопашки. Рукопашный бой — это вообще больная тема. С точки зрения игрока A, A и B находятся рядом, а с точки зрения игрока B, A и B рядом никогда не были. И что тут делать?
Как уже сказали, игра изначально была консольная, так что железо было одинаковым. При низком ФПС на компе отрубается мультиплеер. Так и пишет: "недостаточно кадровой частоты для игры по сети".
В игре есть всякие моменты касательно расчёта столкновений. Например, враг бьёт мечом, и ты попадаешь в зону, которую этот меч накрывает при ударе. Но можно сделать подкат и избежать урона. т.к. при подкате ты какое-то время неуязвим. В зависимости от различных параметров игрового персонажа, эта неуязвимость может быть от 0.13 до 0.53 секунд (вот тут есть некоторая инфа).
Вот интересно, как всё это обсчитывается с учётом имультиплеера.
Что именно подразумевается под задержкой(пингом) от игрока до сервера в статьях и в целом в индустрии. Является ли это число в мc разницей между отправкой и получением ICMP пакета от игрока до сервера, или же всегда подразумевается задержка, с кототорой отправляются UDP пакеты с полезной игровой информацией от игрока до сервера в одну сторону?
Влияет ли как-то количество отображаемых FPS у клиента на получение более свежего состояния мира от сервера до этого клиента?
спасибо! )
FPS как на клиенте так и на сервере безусловно влияет на получение более свежего состояния. Не сложно посчитать, что в худшем случае пингг возрастает на время равное 1/FPS, причем это верно как для FPS сервера, так и игровой машины.
Теперь я знаю, как это правильно делать, спасибо!
Мультиплеер в быстрых играх (Часть IV: Хэдшот! Путешествуем во времени)