Pull to refresh

Comments 56

В старкрафте задержка между действием пользователя и тиком, в котором его планируется обработать, называется Latency и настраивается в опциях. Все машинки во время сетевой игры связаны каждая с каждой, и каждая каждой отправляет действия игрока за текущий тик. Если действий не было, всё равно отправляется пустой кадр. И пока каждая машина не получит от всех остальных кадры действий, к обсчёту тика она не приступает.
Можно добавить, что иногда для детерминированности вычислений используют числа с фиксированной запятой, или даже программную реализацию плавающей точки (например, Spring TA)
для подключения нового игрока ему должно быть передано полное состояние игры.

Интересно, а почему нельзя передать «только команды, вводимые игроками»?
Ему придётся просчитать всю игру до точки подключения, что тоже весьма немало.
Да это понятно, но автор почему-то этот вариант даже не рассматривает. Мне и интересно, почему.
Наверное, потому что это долго.
Не думаю, что это было бы слишком долго.

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

А вот передать текущее состояние игры — это, по сути, передать файл сохраненки (который, рискну предположить, весит мегабайты, на край десятки мегабайт).

Это могло бы выглядеть так: у всех игроков картинка останавливается, на экран вываливается BSOD табличка вида «Опс! Вася выпал из игры. Подождем, пока Вася синхронизируется (две с половиной минуты) или ну его?». В зависимости от настроек, да хоть голосования принимается решение на синхронизацию, все идут пить чай и курить, а Вася тем временем получает десяток, да хоть сотню мегабайт текущей сцены. Посредством p2p сцену можно раскроить на части от разных игроков и заполнить Васе весь канал, тут даже докурить не успеешь.

То же самое и для подключения нового игрока.

В общем, не похоже, чтобы это было сложно реализовать, и такая функция была бы затребована многими. Уж лучше подождать, чем всю игру похерить.
Бля. Надо было дочитать комментарии до конца. Извините.
Ну, в конкретном случае (Supreme Commander) иногда не то что синхронизироваться, но и играть не всегда выходит нормально. Даже на сильных машинах скорость игры на 8 игроков и много юнитов на каждого, скорость время от времени очень сильно падает, хотя FPS остаётся на приемлемом уровне больше 20-30. Это раз. А во-вторых, присоединяться к игре, когда всюду уже враги с отстроенными базами — весьма сомнительное удовольтвие.
А не проще играть с одной машины? Архитектура клиент-сервер? Один синхронизатор, другие игроки. Команды от клиента передаются UDP также как и видимый обзор на экране, а получает клиент UDP поток с командами юнитов. 3000 на несколько байт не так уж много. А то в Вашей схеме сложно за читерством следить
За читерством следить как раз несложно. Как только один игрок изменит состояние игры, хеши не сойдутся и произойдёт рассинхронизация. Бац, game over. Чтобы успешно обманывать других, читеру придётся заменить движок у всех участников игры, а это практически нереально.
Можно читерить, убирая туман войны.
Да, но это уже уровень представления.
Такие программы называются мэпхаки. Патчат клиент и отключают туман войны. Есть противоядие. Когда проводят турниры, старкрафт запускают из-под монитора, который прочёсывает память игры и контрольные суммы считает. Монитор потом отчитывается, что клиент чист. Игрок без монитора не допускается до соревнований.

Как раз чтобы обойти защиту, я отреверсил протокол старкрафта и с соседнего компьютера сниффил трафик. По сути, как раз и убирал туман войны.
Можешь немного рассказать о протоколе старкрафта?
Может там есть свежие решения.
Собственно, статья совершенно правильно описывает то, как оно происходит и в старкрафте.
От игроков передаются их действия: выделил здание, нажал «строить танк», выделил группу N, кликнул правой кнопкой в такие-то координаты и т.д. По сути, даже если действие не удалось (нет денег на постройку танка), команда всё равно проходит.
Меня всегда останавливало от подобных вещей требование второго компьютера. Ну и сложность протоколов больших игр конечно.
Так все-таки почему не клиент-сервер?
Плюс к клиент-серверу добавить пиртупир с синхронизацией чексум если коннект лучше к пиру.
Тогда не надо было бы городить командный конвеер и синхронизатор.
1. Потому что игры зачастую используют 100% мощности компьютера для генерации ui
2. Потомучто снижается отзывчивость ui
3. Потомучто обычно люди играют 1-на-1 и не могут позволить себе отдельный сервер для игры

Как-то так наверно
Потому что дорого! Пусть в текущий момент проходит 100тыс игр в SC2. Где взять 100тыс серверов? Ну хорошо, пусть один сервер держит 5игр ( там же симуляция ). 20тыс серверов — это огромные и очень дорогие мощности.
Нет доверия к серверу. Если хакер контролирует сервер, он себе сможет денег дорисовать. Если сервер делать на мощностях оператора игры, это слишком дорого выйдет.
Да ладно, а шутеры типа q3 как работают? Сервер может быть на одном из клиентов (который «создает» игру). Не так и много ресурсов кушает сервер, если не играть большой толпой и движок нормально оптимизирован.
Про шутеры ничего не знаю — не люблю их. Может быть, там и возможен читинг. По крайней мере, автоприцел в doom2 я до сих пор помню :)
Важно, что сервер может быть на клиенте и тот, при наличии запаса мощности, не помрет, а будет нормально работать.
До какой-то степени, автоприцел в думе — встроенная фишка (при небольшой разнице углов между прицелом и целью). Хотя, конечно, в шутерах читов может быть больше потому, что там больше завязано на человеческом факторе и компьютер (чип-программа) справится с таким значительно лучше.
А что делать с действиями, которые скрыты от других игроков (прим. туман войны)? Передавать, предполагая что клиент не изменят?
Видимо да ) Что ж ещё остаётся.
А зачем их вообще отображать на экране?
Тумана сверху напустил — и гуляй.
Да, все клиенты имеют полною информацию обо всех юнитах/действиях остальных игроков.
Map хаки никто не отменял. :) В том же старкрафте 2 они присутствуют. Вот интересно, а нельзя ли сделать клиент-сервер-клиент?

Кстати проблем с синхронизацией за кучу игр в SC2 не замечал, скорее всего, методы восстановления хорошие. Если что-то идет не так, SC2 просто вешает табличку, что у игрока плохой коннект.

Так же заметил, что если кто-то из observerов лагает, то это не сильно влияет на ping для игроков, разве что он совсем вываливается.

В общем хочу сказать, что сетевой код в Starcraft 2 довольно высокого качества, я например спокойно играю на американском сервере, хотя задержка чувствуется, но не критичная.
Интересная статья, спасибо за перевод!
По моему, отсутствие сноски только добавляло драмы =)
> Кстати, по той же причине многие стратегии не поддерживают подключение новых игроков по ходу игры — для подключения нового игрока ему должно быть передано полное состояние игры. Для игры с тремя тысячами юнитов это займет слишком много времени.

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

Единственное, что не очень ясно — почему в случае рассинхронизации нельзя поставить игру на паузу и, так сказать, голосованием попытаться решить проблему. То есть если игроков больше двух, то скорее всего, как я понимаю, проблема случится у одного. Тогда, сравнивая хеши, можно понять, у кого вариант дефектный, и передать ему полное состояние игры. Да, это вызовет паузу — но всё лучше, чем просто закрывать игру…
Никто не гарантирует, как часто может возникать рассинхронизация. Если она возникает из-за ошибки в логике игры, то она может повторяться чуть не не каждый кадр, тут голосования не спасут.
Хм, когда мы играли с другом в StarCraft через дозвон (даже не через интернет), бывали лаги на линии — тогда появлялось окошко с обратным отсчётом и, как правило, исчезало до окончания отсчёта, что позволяет предположить некий механизм восстановления. Аналогичная ситуация была и позже, с игрой по UDP.
Это скорее просто «ожидание ответа от другого игрока».
Не понимаю два момента.

Стратегия — по определению предполагает задержку в исполнении. Нет проблемы, если юниты начнут двигаться через 0.5 секунды после команды. Можно это обыграть как «задержку передачи информации через спутник» на поле боя.

Даже интересно было бы довести до абсурда — принудительная задержка в 20 секунд.
Т.е. можешь дать инструкции на ближайшие 20 секунд, но реактивного управления не получится. Сколько там до луны идет сигнал? :)

В чем проблема передать состояния 3000 юнитов? Там что, гигабайты данных?
Упакуется все это в 10-15 килобайт. Можно даже табличку вывесить «синхронизация».
Отрубать трехчасовую партию из за рассинхрона — дикое свинство.
Игроки про-уровня не воспринимают всерьез даже игры по интернету, все серьезные соревнования — только по lan-у. Сколько там разница в скорости? 50-100ms?) А вы говорите задержка в полсекунды..)
игроки про уровня не воспринимают даже юнитов и анимацию, они воспринимают только численные количества ресурсов, времени и урона.
>Нет проблемы, если юниты начнут двигаться через 0.5 секунды после команды.
А вот основной пользователь (геймер) думает по-другому. Игра — она же для них в первую очередь, а не чтоб «программистам было удобнее».
>Отрубать трехчасовую партию из за рассинхрона
«рассинхрон» — это не обычные сетевые «тормоза», это свидетельство бага в движке. Что-то типа «assert сработал».
У профессиональных игроков в старкрафт APM (Actions Per Minute) доходит до 300. Средний APM в течении 30ти минутного раунда может быть в районе 200. С задержками в 500мс играть не станут даже новички.
Задержка — это не табу (и частенько встречаются), но при полном переходе получится совсем другая игра. Более требовательная к игрокам и менее зрелищная. Как следствие — менее интересная среднему игроку (и издателю).
Поконтролили-бы вы мутастэк.
Хорошая статья!
С рассинхронизациями действительно сложно бороться, однако вполне возможно. Для этого должен быть механизм записи реплеев. А также контрольную сумму нужно уметь считать по-объектно. Да, при реальной игре этого не надо ( тормозит ), но для починки бага — самое оно.
По поводу борьбы с рассинхронизацией у конечного пользователя. Можно в систему p2p ввести сервер, который будет хранить корректное состояние мира ( которое подтвердили все клиенты ). Пусть оно будет не часто обновляться, однако в случае рассинхрона, можно откатить всех клиентов на него и продолжить игру.
Где-то близко проблема reconnect'а. Она также решается заливанием на клиента полного состояния мира и запуска симуляции. Тут конечно зависит от размера мира. Но думаю даже пару мегабайт можно себе позволить передать. Можно без сервера, каждый клиент передает свою часть мира…
С задержкой можно бороться так. Клиент кликает, юниты идут сразу, но на клиенте, локально. Потом они уже «подстраиваются» под симуляцию. Что-то типа асинхронного движения. Вполне работает :)
эта проблема родилась в эпоху медленного и дорогого интернета, со временем движки смогут быть более требовательны к такого рода запросам пользователей…
Для диагностики рассинхрона можно сделать следующее: во-первых, при несовпадении контрольных сумм сравнивать с другими участниками игры, если у этого компа значения отличаются, а у остальных одинаковые — вероятнее всего, этот комп и есть бажный. После того, как мы получаем это предположение, мы можем на бажном компе сделать более качественный подсчет хешей — скажем, не брать хеш от всего состояния игры, а разбить эти состояния на подсостояния, и у каждого посчитать хеш. Таким образом будет легче локализовать место рассинхрона. Ну и обязательно нужно взять 2 реплея до момента рассинхронизации — один с бажной машины, другой с машины, на которой, вероятно, все в порядке (а то вдруг еще бага в записи реплеев присутствует). И после всего этого нужна тулза, которая бы симулировала по шагам, по самым минимальным итерациям ход игры по этим двум реплеям, постоянно сравнивая их. Правда это не поможет, если бага воспроизводится только на конкретной машине и не зависит полностью от реплея.
Действительно — протокол, основанный на командах ввода от игрока — великая вещь. Он позволил нам сделать повторы игр. (Пример: http://www.snailz.ru/replay/?id=285274&p=124,100&s=24&cp=640x561 — нужно нажать на кнопку «play»). Но нам не удалось достичь полного синхрона — часто у клиентов разные версии flash-playerа — в итоге по разному обрабатывался колижн и т.п. Если объектов в игре немного, то в целях экономии времени, лучше делать синхронизацию по координатам в ключевых моментах.
Хотелось бы добавить о причинах рассинхронизации. Кроме упомянутых в статье случаев с ошибками округлений чисел с плавающей точкой ( лечится ), и ошибкой не инициализированной переменной ( борются, повышая культуру программирования ), есть еще одна неприятная причина рассинхронизации. Когда симуляция начинает зависеть ( часто очень не явно ) от пользовательского слоя. Простейший случай — в симуляции взяли позицию не у мирового объекта ( который участвует в симуляции ), а у клиентского.
Как же интересно читать о внутреннем устройстве любимых игр!)
UFO landed and left these words here
Only those users with full accounts are able to leave comments. Log in, please.