Искусство обмана

Aug 30, 2012 15:11


Это немного причесанная версия моего рассказа по аське про особенности геймдева. Везде, где можно было соврать для красного словца, я так и делал :)

Мой коллега правил адский баг в сетевой игре Splinter Cell Conviction. Следует сделать небольшое отступление и рассказать, как сейчас пишутся все сетевые игры. Считают одно и то же детерминировано на разных машинах, подавая в движок на обоих ввод от обоих машин. Если в игре происходит лаг, то детерминировано откатывают движок на какое-то число шагов и подают снова все данные, как будто лага не было. В процессе игры, чтобы убедиться, что все считается, как положено и никто не читерит, считаются хэш-суммы от состояния мира и сравниваются. Если отличаются, происходит рассинхронизация, и игра прекращается.

В итоге и архитектура любой современной игры диктуется как раз сетевой частью. То есть, например, необходимо строгое разделение на ввод, интерпретацию ввода и движок, потому что интерпретация ввода пересылается по сети. Опять же, движок должен версионировать все объекты, чтобы иметь возможность откатиться, иначе возможна ситуация, когда присылает ему другой хост «я на 100500-м фрейме тебе в голову выстрелил», а тот уже 9000 фреймов посчитал без учета этого.

Так вот, в Conviction происходила рассинхронизация. И оказалось, что в геймплее в некоторых местах используется генератор случайных чисел. Если ГСЧ инициализирован одинаковым seedом, то он всегда выдает одну и ту же последовательность, следовательно, процесс детерминирован и рассинхронизации никогда не будет. Вот только на маке в качестве компилятора использовался gcc, а у него другой ГСЧ, который с тем же seedом выдает другую последовательность :) Пришлось совершить много магии, чтобы понять, как восстановить детерминизм во всех случаях.

Детерминизм должен работать на машинах с разными компиляторами, разными процессорами. Самое веселое начинается, когда double-арифметика чуть-чуть отличается. Это сложно не заметить, выскакивает, что хэши состояний движка не совпали и игре каюк, но очень сложно отладить. Поэтому из-за проблем с вещественными числами их часто моделируют fixed-point арифметикой, в предположении, что целые числа-то наверняка везде работают одинаково. Вот только корни и синусы считать в целых числах не очень удобно, так и появляются всякие fast inverse square root от Кармака :) Мы будто говорим, что нас не волнует, что это не совсем та функция, она близка и считается быстро и детерминировано. Особенно забавно, когда это что-то заметно нарушает, скажем, считаем мы какую-нибудь касательную, а она из-за этих хитрых псевдокорней вообще ничего не касается. Или синус чего-нибудь считаешь, а он больше 1 :)

Помимо этого есть алгоритмы компенсации причинности :) Допустим, игроку выстрелили в голову, пройдя через открытую на одном хосте дверь, при том, что на своем хосте он ее уже закрыл. И надо как-то это скомпенсировать. В чью-то пользу рассудить? В пользу выстрела? Оказывается, зависит от геймдизайна. Если игра киберспортивная, то в пользу сильнейшего игрока, если фановая, то в пользу слабейшего :) Известный геймдевелопер Борис Баткин рассказывал в блоге о разработке баскетбола: сильный игрок при честном ГСЧ очень быстро уходит в отрыв в счете, играть становится неинтересно. Подкрутили ГСЧ и сильные игроки стали жаловаться, что игра подыгрывает слабым. В итоге они сделали, наконец, модель такую, что игроки вроде чувствуют, что их где-то надурили, но где именно - понять не могут :)

У вас еще не возникло желания заняться геймдевом? :) Он такой весь неожиданный, ВНЕЗАПНЫЙ. Часто думаешь, что какая-то задача чисто техническая, смотришь - опа, а не получается, никак, не укладывается по времени или еще по чему, или по сети не получится такое передавать без лага. И вдруг понимаешь, что можно просто обмануть пользователя или сделать частью геймдизайна.

Вообще немного ирреальное ощущение создается, когда впервые смотришь на отрисовываемый уровень с отвязанной камерой. Бегаешь внутри - замечательно, все как настоящее! Отвязываешь камеру - опа, да этот дом просто нарисован на плоскости. Опа, от этого коридора, по которому я только что прошел, осталась только одна стеночка. Опа, здесь были кустики, а теперь только топорный лод. Фигасе, у этого камня нет обратной стороны, и правда, я ведь никогда не заходил за него. В рот мне ноги, этот великолепный водопад - три полигона со скролящейся текстурой. До сих пор помню свое удивление, когда увидел вайрфрейм очень красивой заставки конквикшна, где дымок так красиво вьется вокруг дырок от выстрелов. Я видел эти мелкие пляшущие пылинки и думал, ого, сколько же их тут. Оказалось, что это хитрым образом плясали 4 полигона с текстурой.



Я дом, я не хочу стоять на земле. Я хочу светить окнами верхних этажей на горизонте.

Меня поражало, как здорово сделано освещение. То есть не просто тупая тень, а место, куда меньше света отражается, темнее, что-то типа global illumination. Это ж изрядно надо рейтрейсить, чтобы такого добиться, думал я, а как вот они просекают это отражение от той стены? Оказалось, что это предрассчитанные текстуры global illumination и при реалтаймовом рендеринге ничего не считалось :) Или: обалдеть, как же классно пляшут блики огня на стене! Текстура :) Или: ого, как круто стенка дырявится от пуль. А это декали с параллакс мэппингом, да еще и наложенные по паттерну, а не туда, куда они на самом деле легли, ведь ты ж не успеваешь заметить, где именно летела пуля :)

Геймдев это искусство компромисса между наглостью обмана мешка с мясом и сложностью программирования. Думаешь, что этот враг настоящий и дьявольски умен и хитер? А у него раунд-робин из трех тупых действий. И ты бы, наверно, заметил это, если бы он перед этим в кинематографическом ролике не затулил какую-нибудь суровую штуку. Другими словами, происходит именно обман восприятия. Ты бы мог выявить алгоритм, если бы не был запутан другими составляющими игры. Вот еще забавный момент. Почему я считаю Кейт Арчер из NOLF1 намного более настоящей, чем в NOLF2, хотя в ней раз в 10 меньше полигонов? Потому что там постоянно есть вставки, где она общается с начальством и подкалывает его :)



Слева - настоящая Кейт!

А иногда ты допускаешь багу и тогда эффект становится вообще загадочным :) Скажем, ты начинаешь замечать обман! Он всегда тут был, так и задумано, но теперь ты его почему-то видишь. Самое жесткое, когда она не вылетает, и вроде все правильно, просто ты почему-то не был введен им в заблуждение. Смотришь на картинку и думаешь - что-то тут не то. А потом: вот оно что, тут же в том дальнем зеркале картинка перевернутая! Потому что в опенгле координаты от −1 до 1, а в директиксе от 0 до 1! Потому что на самом деле это не зеркало. Это сцена, отрендеренная в текстуру с точки зрения за зеркалом, и если текстуру наложить не с теми координатами, картинка будет перевернутая. Получается эдакий мир Зазеркалья, где все страньше и страньше. Оп - и в зеркале отражение перевернутое. Или НЕ ЗЕРКАЛЬНОЕ. Представь, подходишь ты к настоящему зеркалу и чувствуешь, что что-то не то :) А отражение-то не зеркальное :) Есть какая-то ошибка в коде, она не влияет на работоспособность, на логику, вообще ни на что не влияет. Просто обман становится чуть менее убедительным.

Самое стремное, конечно, это когда делаешь что-то, а все равно кажется, что получается плохо. Особенно это характерно для воды :) Как воду не сделай, если нет правдоподобного окружения, ты в нее не поверишь. Поставил в скайбокс какую-нибудь жатую-пережатую картинку - обалдеть, как настоящая! Аналогично с металлами. Глаза не верят в металлы, в которых ничего не отражается, поэтому на мечи накладывают сильно упрощенную текстуру с небом и землей, иначе же они выглядят пластиковыми. Трава тоже редкая жесть. Обычно это тупо биллборды с полупрозрачной текстурой, текстура для подальше и полигоны только для той травы, по которой топает герой. Потому что глаз определяет, брехня эта трава или нет, по тому, как она реагирует на его действия. Если ветер подул - неизвестно, как он подул, может именно так она и будет качаться. А если наступил, то трава должна примяться. Вот и получается 100500 полигонов на квадратный метр травы вокруг героя и 10 полигонов на всю остальную.



Угадай, где текстура, а где куча полигонов?

При первой встрече с внутренностями компьютерных игр часто происходит суровый культурный шок. Мы привыкли, что то, что мы видим, везде примерно одинаковое. Зайдем с другой стороны - оно не исчезнет. Травинка рядом такая же по размеру, как и травинка вдалеке, и если к ней подойдем - на ощупь будет такая же. Что на дереве уйма листиков. Что почти все предметы отражают свет, в том числе и на другие предметы. В играх все не так, и это плющит еще круче, чем «Матрица» вместе с «Тринадцатым этажом». Потому что это Реальность, созданная с минимальными затратами труда, исключительно для того, чтобы тебя обмануть.

Любое искусство заставляет нас верить во что-то выдуманное, скажем, исключительное впечатление оставляет история создания «Властелина Колец» (гигантские миниатюры, двигающиеся столы, две копии Хоббитона, MASSIVE), но именно в геймдеве конфликт между ограниченными способностями воздействия и реалистичностью обмана становится наиболее заметен. Я так думаю, что вампиры Уоттса не смогут заниматься геймдевом :))

игры, программирование

Previous post Next post
Up