суббота, 24 сентября 2011 г.

Как работает компенсация лагов в Left 4 Dead (Source engine)



Итак, игра у нас типичная и клиент-серверная, где сервер занимается следующими вещами:

• симуляция мира вокруг
• отработка движка игры
• обработка командочек пользователя
• игровой мир рассчитывается каждые N ms (эта штука называется внутренний tickrate сервера, для l4d1 и l4d2 = 30)

Клиент посылает серверу команды по UDP

• клиент получает эти данные, и на основе них генерит вам картину мира, воспроизводит звуки, события итп
UDP это такие пакетики по 10-200байт, без установления соединения, в отличие от TCP, примерно 20 байт служебной инфы + данные
• посылается примерно 20-30 пакетов в секунду, это и есть серверный cmd_rate - он может быть от 20 до 30.
• клиент может пожаловаться серверу что он имеет плохой канал итп.. и запросить "худшие" значения по качеству вот этими параметрами
sv_minrate\sv_maxrate - мин и макс значение в байтах сколько он готов принимать
sv_minupdaterate\sv_maxupdaterate - то же самое в командах
cl_updaterate - а это типа дефолтное "рабочее" значение
• поскольку сервер не может посылать обновления клиенту при каждом изменении мира, он буферизует и посылает дельту - что изменилось для каждого клиента с момента последнего пакета отправленного только этому клиенту :)
• полные "обновления" посылаются толлько при загрузке игры, затем шлется только дельта




итак, от чего зависит качество вашей игры

• загрузка цп клиента
• канал клиента
• загрузка цп сервера
• канал сервера
• потери пакетов
• среднее время на прием и предачу ответа от сервера (ping или round trip time)

[ если вы дочитали до сюда, и что-то поняли уже хорошо :) ]

чтобы игра была интересной важно чтобы доли секунды реально что-то значили.

итак чтобы бороться со всей этой фигней, в движке source встроено аж 3 механизма

1. entity interpolation (предсказание поведения физики\объектов карты на клиенте)


это работает следующим образом

• берется n последних пакетов (cl_extrapolate_amount), берется ваш текущий FPS (cl_showfps 1) и рассчитывается следующий кадр и местоположение объектов для которых физика и считается (полет ящика, бросок канистры, танк пнул машинку)
• если пакеты доходят с потерями - то буфер старых пакетов пуст и делать интерполяцию особо не по чему - тут вступает в игру экстраполяция (cl_extrapolate 1) - движок на клиенте пытается округлить вперед (уже довольно грубо) что же творится на карте.
• эффект экстраполяции ограничен по времени - 0.25s после последнего пакета с сервера - чтобы не внести сильные искажения

• итак вот мы пришли к cl_interp
cl_interp = ну это каждый задрот знает ;) = cl_interp_ratio / cl_updaterate
где
cl_interp_ratio = сколько последних пакетов использовать для "округления" вашей картины мира (чем больше = тем дальше от реальности на сервере, но тем плавнее)
cl_updaterate = кол-во команд с сервера, в общем то это константа равная 20..30

2. input prediction (предсказание ввода)


допустим у нас пинг 150ms и мы нажали w - сервер узнает об этом только чз 150ms; еще через некоторое время он рассчитает куда же мы переместились; потом он разошлет это всем другим клиентам; и нам придет назад пакет с информацией; и тут мы уже "реально" переместились вперед на метр... как-то так

чтобы не было таких дерганий - движок на клиенте САМ двигает нас вперед не дожидаясь подтверждения от сервера (замечу - реальность на сервере - САМАЯ правильная, т.е. то что на клиенте - неважно)

поэтому так бывает - мы куда-то забежали - клиент это показал - сервер подумал и исправил неправильное округление клиента - вернув назад нас же резким рывком :\

• вся эта котовасия включается по дефолту (cl_predict 1)
• само сглаживание происходит на время cl_smoothtime

3. lag compensation (предсказание действий других игроков)


если вы смогли понять предыдущие, то это вообще взрыв мозга xD

тут кейс такой, мы видим врага бегущего мимо и стреляем ему в голову

• мы жмем ЛКМ 8)

• X ms пакет с инф о выстреле пакуется

• Y ms он едет на сервер

• Zms сервер его переваривает, и через время Z+Y+X ваш враг уже убежал..

что же делает движок?

• он помнит все события на сервере за последнюю секунду... при этом он отматывает НАЗАД!!! время и проверяет где тогда был ваш враг - если он был на линии выстрела - засчитывается хит.. бабац. попали.. и во время очередного тика на сервере всем клиентам рассылается информация что вы попали..

именно за счет lag compensation появляются вот такие перлы

(игроки часто думают что это баг игры.. лол)


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

• всё это side-effect от lag compensation.
итого имеем lag compensation + entity interpolation + client prediction,
именно поэтому так важен низкий пинг и отсутствие потерь - иначе косячные атаки, длинные руки, тормозящие насмерть зомби и прочая ерунда.


P.S.

основной фокус этого текста - объяснить как оно работать внутри,

как настроить cl_interp получше уже давно описано много где.. например тут (http://www.deadzone.ru/forum/showthread.php?t=3536 )


вот еще видео с хантером, где даже народ не понимает что происходит и думает что это баг



аналогичное для Counter-Strike Source

четверг, 22 сентября 2011 г.

Внутреннее устройство Left 4 Dead (Source engine)

На просторах сети нашел интересную презентацию о том, как работает AI, pathfinding и прочие аспекты в игре Left 4 Dead от разработчиков Valve (Counter-Strike 1.6, Counter-Strike:Source, Half-Life 1-2, Portal 1-2



Краткое саммари целей разработчиков этого шутера.

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

- зомби бегают по разному, но предсказуемо;
- бегают по касательной, относительно работы вот этого алгоритма поиска маршрута для стаи — A* ();
- различные эвристики при поиске дырок в карте;
- умеют залезать на любые поверхности — сами решают где и какие;
- подсистемы - навигация, управление телом, управление видимыми целями, выбор жертвы.

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

• Реиграбельность — основные подходы.
- структурный рандом — Valve, исходя из опыта предыдущих игр, говорит о том, что при генерации среды, игроки для выживания не тупо запоминают, что где на уровне, а вынуждены менять тактику, и собственно нарабатывать скилл — это и привлекает геймеров;
- рандом в игре не произвольный, а задаваемый различными граничными значениями, который задает дизайнер уровня; если чтото генерируется, то пачкой\сгустками по карте; нет ни равномерного засеивания ни пустых локаций;
- AI-директор использует уровень «стресса» каждого игрока, чтобы понимать, стоит его атаковать или нет, % зомби, которые должны атаковать спереди и сзади, для всей карты рассчитывается градиент, чтобы понять, какие координаты приближают к убежищу, а какие нет (т.е. где конечная цель);
- для выгрузки лишних зомби используется техника Active area set, т.е. все зомби которые отстали, сгенерируются потом впереди; на локациях которых мы не видим нет предметов и зомби для экономии ресурсов; запоминается какие локации игрок видел а какие нет и т.п.

• Драматизм игры.
- популяции мобов, атаки — всё делается волнами. т.е. атака нарастает, затем затишье;
- уровень стресса считается при каждом ударе зомби по игроку;
- по мере того как команда отбивается и недостаточно мобов атакует, Директор может добавлять повышенные количества мобов, чтобы повысить уровень стресса и так же резко их убирать, видимо этим и достигается то, что в игре атака временами так резко обрывается, и бесконечная орда так легко пропадает.



The AI Systems of Left 4 Dead


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



примеры видео

1я часть



2я часть

среда, 14 сентября 2011 г.

Аналогии кодеров и геймеров

И там и там


  • бинарное деление на "профи" и нубов, каждый кто лучше тебя - профи (или "задрот"), кто хуже - новичек (или "noob") и не достоин внимания :) .. наиболее явно проявляется на интервью - мужики рассказывают о том какой крутой проект они пилят, и с улыбкой слушают твои доводы о том что ты вроде тоже не в носу ковырялся (и это не зависит от компании, даже в средней есть умельцы загибать пальцы)
  • формируется некоторая тусовка людей со скиллами, со своими ценностями и со своим видением идеального про-спеца; минимальный уровень "трюков" который с вами будут обсуждать - что-то около 80% от максимума в команде, т.е. простые вещи не вызывают интереса 
  • в команде быстро выявляется неформальный лидер который "тащит" за собой остальных, независимо от их настроя, даже когда перспективы решить поставленную задачу туманны  и шансов на "победу" нет :)
  • при разговоре на кодерском собеседовании оппонент тупо сравнивает твой скилл с тем что он знает, и с локальным стандартом в его окружении\компании
  • *NEW и там и там человек редко верит что есть кто-то выше его по скиллу, пока его не порвут на тряпки 8)
  • *NEW самый скилловый старается держать дистанцию и всем видом показать что он де суров и знает ответы на все вопросы.. ну а если не знает\налажал то ты\команда не так поставили задачу\не подстраховали итп)
  • как правило - довольно молодой коллектив, отсюда и максимализм, и желание помериться известно чем по любому поводу...  особенно у интервьюверов (за редким исключением) принято показать кандидату что мол нифига то ты нубас не знаешь :] 
  • и там и там при высоком уровне исполнителей даже без контроля, подготовки, тренировок может выйти достаточно хороший результат; при плохих кадрах и там и там FAIL.
  • не так важно какая роль у тебя в команде - тим лид, капитан, менеджер; куда важнее общий средний скилл команды, навыки каждого персонально, и известность команды; быть средним звеном в топ-team лучше чем быть главным в никому неизвестном болоте.