После выпуска Uncharted 4 я уже могу рассказать о том, над чем работал в этом проекте. В основном я разрабатывал ИИ для напарников игрока в однопользовательском режиме и помощников в многопользовательском, а также немного работал над геймплейной логикой. Я опущу те аспекты, которые не добрались до готовой игры и некоторые мелкие детали.
Итак, приступаем:
Система постов
Прежде чем начать, я хотел бы рассказать о использованной у NPC системе постов. Я не работал над ядром логики этой системы, а помогал писать клиентский код, который её использовал.
Посты — это дискретные позиции в пространстве навигации NPC, в основном создаваемые инструментами разработки и вручную размещаемые дизайнерами. В зависимости от наших потребностей, мы могли создавать различные селекторы постов для оценки разных типов постов (например, селектор постов скрытности, селектор боевых постов) и выбирать пост с самой высокой оценкой, чтобы отправить туда NPC.
Напарники, следующие за игроком
Система следования напарников за игроком взята из The Last of Us.
Основная идея заключалась в том, что напарники выбирают вокруг игрока позиции, в которые нужно следовать. Эти потенциальные позиции расходятся от игрока и должны удовлетворять следующим проверкам свободности прямолинейного пути: от игрока до позиции, от позиции до спроецированной вперёд позиции, от спроецированной вперёд позиции до игрока.
В отличие от The Last of Us, в Uncharted 4 есть такой аспект, как скалолазание. Чтобы встроить скалолазание в систему следования за игроком, мы добавили селектор постов скалолазания, выбирающий точки, в которые напарники должны перемещаться, когда игрок взбирается по скалам.
Эта задача оказалась сложнее, чем мы ожидали. Недостаточно было просто приказать напарникам использовать обычную логику следования, когда игрок не взбирается, и менять посты, когда игрок ползёт по стене. Если игрок быстро переключается между обычным состоянием и скалолазанием, напарники начинают колебаться между этими двумя состояниями. Поэтому мы добавили гистерезис: напарники теперь могут менять состояние, только когда игрок сменил состояние и достаточно далеко переместился в этом состоянии. В общем случае гистерезис — это хороший приём, позволяющий избежать «поведенческих скачков».
Идущие впереди напарники
Мы хотели, чтобы в некоторых моментах игры напарники показывали игроку путь. Эта система была взята из The Last of Us и усовершенствована: дизайнеры использовали сплайны, чтобы наметить общие пути, по которым должны следовать напарники, ведущие игрока вперёд.
В случае наличия на уровне нескольких путей дизайнеры располагали несколько сплайнов и включали/отключали их с помощью скрипта.
Позиция игрока проецируется на сплайн, а опорная точка сопровождения игрока располагается впереди, на расстоянии, настраиваемом дизайнерами. Когда эта опорная точка сопровождения минует контрольную точку сплайна, помеченную как точка ожидания, напарник начинает двигаться к другой точке ожидания. Если игрок решает вернуться назад, то напарник начинает возвращаться, только когда опорная точка сопровождения оказывается слишком далеко от наиболее удалённой точки ожидания, пройденной в процессе последнего движения вперёд. Таким образом, снова образуется гистерезис, позволяющий избегать резкой смены состояний.
Также мы встроили в систему сопровождения динамическую скорость движения. На основании расстояния между напарником и игроком вдоль сплайна располагаются «плоскости скоростей». NPC могут использовать три типа движения: ходьба, бег и спринт. В зависимости от плоскости скоростей, в которой находится игрок, напарник выбирает соответствующий тип движения, чтобы сохранять необходимую дистанцию до игрока. В соответствии со своим видением дизайнеры могут включать и отключать плоскости скоростей. Кроме того, в зависимости от расстояния до игрока скорость анимации движения напарника слегка увеличивается или уменьшается, чтобы избежать резкой смены скорости движения при переключении между типами движения.
Совместное использование укрытий
В The Last of Us игрок может перемещаться относительно напарника, по-прежнему оставаясь в укрытии. Это называется общим укрытием.
В The Last of Us Джоэл находится дальше от стены укрытия, чем Элли или Тесс, и это логично, потому что они меньше, чем Джоел. Но для Нейта, Сэма, Салли и Елены это выглядело бы неестественно, ведь они имеют почти одинаковый рост. Кроме того, Uncharted 4 гораздо более быстрая игра, и если Нейт будет вытягивать руки, перемещаясь за препятствием, это разрушит плавность движений. Поэтому мы решили, что напарники просто станут опираться на стену укрытия, а Нейт будет слегка огибать их при движении.
Здесь мы использовали очень простую логику. Если спроецированная позиция игрока с учётом его скорости попадает в прямоугольную границу вокруг поста укрытия напарника, то напарник завершает текущее поведение за препятствием и прижимается к стене укрытия.
Медики-помощники
Медики-помощники в многопользовательском режиме требуют совершенно нового поведения, которое отсутствует в однопользовательском режиме: они должны воскрешать поверженных друзей и копировать поведения игроков за укрытиями.
Медики пытаются имитировать поведение игроков за укрытиями и быть как можно ближе к игроку, чтобы в случае ранения игрока находиться рядом и воскресить его. Если ближайший союзник ранен, они также будут воскрешать и союзника, при условии, если игрок ещё жив. Если игрок оснащён модом RevivePak для медиков, то прежде чем бежать к союзникам для из воскрешения они будут пытаться бросать в союзников RevivePak (несколько одновременно выполняемых воскрешений ускоряют процесс воскрешения); при бросках RevivePak используется логика метания гранат, в частности, проверка свободности траектории и воспроизведение анимации, только гранаты заменены на RevivePak.
Трава для стелса
Новой механикой Uncharted 4 также является скрытное перемещение в траве. Для его реализации нам нужно было каким-то образом разметить окружение, чтобы геймплейная логика игрока узнавала, находится ли игрок в траве. Изначально мы хотели, чтобы разметкой поверхностей коллизий травы занимались в Maya художники по фонам, но выяснили, что коммуникации между художниками и дизайнерами слишком замедляют итерации. Поэтому мы придумали другой способ разметки областей с травой для стелса. Специально для дизайнеров в редактор добавили новый тэг травы для стелса, чтобы они могли с высокой точностью помечать навигационные полигоны, которые игрок должен считать травой для стелса. Благодаря этой дополнительной информации мы смогли также оценивать посты скрытности в зависимости от того, находятся ли они в траве, или нет. Это оказалось полезно для напарников, движущихся, когда игрок находится в режиме стелса.
Органы чувств
Поскольку в отличие от The Last of Us, в Uncharted 4 нет режима прислушивания, нам нужно было каким-то образом сообщать игроку о приближающихся угрозах, чтобы того не напрягало неизвестное расположение врагов. Используя данные о восприятии врагов, мы добавили цветные индикаторы угрозы, сообщающие игроку, что враг скоро его заметит, как отвлекающий фактор (белый индикатор), воспримет как отвлекающий фактор (жёлтый индикатор) и полностью осознает его присутствие (оранжевый индикатор). Кроме того, мы сделали так, чтобы индикатор угрозы усиливал фоновый шум, чтобы нарастить напряжённость, и издавал громкий сигнал, когда враг полностью понимал о присутствии игрока, как в The Last of Us.
Исследование
Это последняя крупная часть геймплея, в разработке которой я принимал участие, прежде чем игра ушла на «золото». Обычно я не посещаю формальные совещания в Naughty Dog, но за несколько месяцев до «золота» у нас проходило не меньше одного совещания в неделю под управлением Брюса Стрейли или Нила Дракманна. Совещания были посвящены ИИ игры. Почти после каждого из этих совещаний в системе исследования находилось что-то для изменения или переработки. Прежде чем выпустить готовую игру, мы прошли через множество этапов итераций.
Есть два аспекта, отвлекающих врагов и побуждающих их к исследованию: присутствие игрока и трупы. Когда враг обнаруживает отвлекающий фактор, он пытается привлечь ближайшего союзника, чтобы вместе исследовать его причину. Более близкий враг становится исследователем, а второй — наблюдателем. Обнаруживший отвлекающий фактор враг может стать исследователем или наблюдателем, и мы подготовили для этих случаев два разных набора диалогов («Там что-то есть. Пойду проверю.» и «Там что-то есть. Иди проверь.»).
Чтобы сделать начало и завершение исследования более естественными, мы отрегулировали тайминги движения врагов и снижение показателей индикаторов тревоги, чтобы пара исследователей не выполняла механистично одинаковые действия в одинаковое время.
Если отвлекающим фактором является труп, то исследователь может узнать о присутствии игрока и приказать всем начать искать его, безвозвратно выйдя из спокойного состояния. Обнаруженный труп тоже помечается, чтобы игрок имел возможность понять, что его выдало.
На некоторых уровнях сложности несколько исследований друг за другом заставляют врагов исследовать более агрессивно, что увеличивает шансы найти игрока, спрятавшегося в траве. На уровне сложности Crushing враги агрессивно исследуют постоянно.
Взгляды в диалогах
Это тоже один из последних аспектов, которыми я занимался в проекте.
Взгляды в диалогах — это логика, заставляющая персонажей реагировать на разговоры, например, смотреть на других людей и делать жесты. В The Last of Us дизайнеры месяцами вручную аннотировали все внутриигровые диалоги, помечая моменты взглядов и жестов. Повторять этого мы не хотели. У нас было несколько заскриптованных диалогов, которые уже разметили вручную, но нужна была система, способная обрабатывать диалоги без аннотаций. Аниматорам давали параметры для регулировки скорости поворота головы, максимального угла поворота головы, длительности взгляда, времени пауз, и так далее.
Сохранение скорости движения джипа
С ранних этапов разработки у нас была проблема с этапом гонки на джипе в уровне с городом на Мадакаскаре: если джип игрока заносило и он терял скорость после удара о стену или машину врага, то игрока отбрасывало далеко от конвоя и он проваливал прохождение уровня.
Я придумал такое решение: временно ограничил сверху угловую скорость и изменение линейной скорости при столкновении со стенами и вражескими машинами. Это простое решение оказалось довольно эффективным — игрокам гораздо сложнее стало проваливать прохождение из-за заносов.
Уничтожение транспорта
В Uncharted 4 впервые появились управляемые игроком машины. В предыдущих играх серии водить машины могли только NPC, и эти машины двигались по сплайновым «рельсам». Я помогал в работе над реализацией уничтожения транспорта.
Существует несколько способов уничтожить вражеский транспорт: убить водителя, расстрелять машину, протаранить вражеский мотоцикл своим джипом, ударить джип врага своим, чтобы его занесло. В зависимости от причины уничтожения выбиралась анимация уничтоженного транспорта и его пассажиров. Анимация смешивается с физически управляемыми рэгдоллами, поэтому анимация уничтожения плавно переходит в физически симулируемую аварию.
Для уничтожения мотоциклов тараном использовался ограничивающий прямоугольник в плоскости XZ и точка контакта, позволяющие выбрать одну из четырёх направленных анимаций уничтожения тараном.
В случае с заносами джипов выполняется проверка, не превышает ли отклонение поворота джипа от нужного направления движения порогового значения заноса.
При воспроизведении анимаций уничтожения существует вероятность, что уничтоженный транспорт может пройти сквозь стену. Используется sphere cast (сфера, проецируемая как луч) из идеальной позиции машины вдоль «рельс», если бы она не была уничтожена, к позиции, где на самом деле находится её корпус. Если при генерировании sphere cast фиксируется контакт, то машина сдвигается в направлении нормали контакта на долю величины проникновения, поэтому процесс устранения прохода сквозь стену происходит постепенно, на протяжении нескольких кадров, что позволяет избегать резкой смены позиций.
Мы создали специальный тип уничтожения транспорта, называемые vehicle death hint. Это чувствительные к контексту анимации уничтожения, взаимодействующие с окружением. Аниматоры и дизайнеры располагают позиции этих анимаций вдоль «рельсов» сплайна и указывают окна входа в них на сплайнах. Если транспортное средство уничтожается в пределах этого окна, то начинает воспроизводиться соответствующая анимация уничтожения. Изначально эта функция создавалась как инструмент для реализации эпичного взрыва джипа для демо, представленного на E3 в 2015 году.
Фильтр Байера для дизеринга
Мы хотели избавиться от отсечения геометрии, когда камера слишком приближается к объектам окружения, в основном к листве. Поэтому мы решили затенять пиксели в пиксельном шейдере на основании того, насколько пиксели близки к камере. Мы не могли бы воспользоваться прозрачностью, потому что она слишком затратна, а листвы слишком много. Вместо этого мы применили дизеринг, скомбинировав расстояние от пикселя до камеры и паттерн в виде фильтра Байера — некоторые пиксели полностью отбрасывались, что создавало иллюзию прозрачности.
Наш первоначальный фильтр Байера был матрицей 8×8, показанной на этой странице Википедии. Я решил, что он был слишком мал и приводил к созданию артефактов в виде полос. Мне хотелось использовать фильтр Байера 16×16, но в Интернете я нигде не мог его найти. Поэтому я попытался выполнить обратную разработку паттерна фильтра Байера 8×8 и заметил рекурсивный паттерн. Я мог бы просто изучить его и записать матрицу 16×16 вручную, но я ради интереса написал инструмент, способный генерировать матрицы Байеса размером в любую степень двойки.
После перехода к фильтру Байеса 16×16 артефакты с полосами значительно снизились.
Задержка звука взрыва
На самом деле это очень незначительная деталь, но я хотел бы её упомянуть. За пару недель до показа демо на E3 в 2015 году я заметил, что взрыв башни видится и слышится одновременно, что было нелогично. Нейт и Салли находятся очень далеко от башни, поэтому они должны сначала увидеть взрыв, а потом услышать его. В готовое демо команда художников добавила небольшую задержку звука взрыва.
Локализация на традиционный китайский
Я включил текст и субтитры на традиционном китайском всего за две недели до выпуска игры на «золоте», и обнаружил ошибки в переводе. Большинство ошибок было буквальным переводом с английского на традиционный китайский, который не соответствовал контексту. Я решил, что у меня не будет времени пройти всю игру самостоятельно, параллельно выискивая ошибки перевода. Поэтому я попросил несколько человек из отдела тестирования сыграть в разные части игры на традиционном китайском и просмотрел записанные видео прохождения. Это оказалось довольно эффективным шагом; мне удалось зафиксировать все обнаруженные ошибки перевода, и команда локализаторов смогла исправить их до дедлайна.
Вот и всё
Это практически всё, над чем я работал для Uncharted 4 из того, что стоит упоминания. Надеюсь, статья была вам интересна.
Комментариев нет:
Отправить комментарий