[Перевод] 50 типичных ошибок проектирования игровой камеры (часть 1)

image

Эта статья — перевод выступления Джона Нески (John Nesky) с GDC14.

Джон — один из разработчиков в компании TGC, известной своей игрой Journey. Он начал работать там в роли гейм-дизайнера, но впоследствии увлёкся настройкой работы камеры в Journey, поэтому теперь его должность звучит как Feel Engineer.

Вряд ли вы найдёте какое-нибудь сообщество разработчиков, специализирующихся на игровых камерах. И есть, пожалуй, всего одна книга на эту тему — Real Time Cameras за авторством Марка Хэйг-Хатчинсона (Mark Haigh-Hutchinson). Но хотелось бы глубже изучить эту тему и узнать, как люди решают те или иные трудности.

Тот факт, что к теме камер не приковано большого внимания, неудивителен — пока они работают, как надо, обсуждать их нет нужды. Они становятся заметными тогда, когда делают что-то не так. Игроки начинают обсуждать работу камеры только когда хотят пожаловаться, что она их раздражает.

Поэтому для того чтобы поговорить на тему игровых камер, нужно смириться с ошибками. И в этой статье я расскажу, что может пойти не так, когда вы начнёте проектировать поведение камеры в вашей игре.

За пределами кинематографа


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

Типы игровых камер


image
Бывает три типа игровых камер:

  1. с видом от третьего лица с фиксированным углом съёмки;
  2. от третьего лица с динамическим углом съёмки;
  3. и от первого лица.


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

В первом случае камера расположена далеко от персонажа. Поэтому вам нужно избавиться от всего, что может встать на пути поля обзора и заградить персонаж. Грубо говоря, вы избавляетесь от четвёртой стены. Все двухмерные игры так делают — это касается как игр с видом сбоку, так и с видом сверху (в этом случае вы избавляетесь от потолка, а не от стены).

В случае с видом от первого лица, напротив, расстояние равняется нулю. Камера фактически находится внутри черепа персонажа, поэтому вам не нужно заботиться о том, чтобы камера следила за ним — игрок и так видит мир глазами персонажа. Так что персонаж никогда не скроется из виду, и нет необходимости избавляться от стен или потолков.

Оставшийся тип камер — с видом от третьего лица и динамическим углом съёмки — находится где-то посередине между предыдущими двумя и наследует худшие черты обоих.

Во время разработки Journey мы хотели, чтобы игрок мог детально исследовать мир, поэтому отказались от камеры первого типа. В то же время мы хотели, чтобы игрок мог хорошо видеть своего персонажа, поэтому пришлось отказаться и от камеры с видом от первого лица. Значит, нам нужна была камера, размещённая внутри игрового мира и находящаяся непосредственно рядом с персонажем. Поэтому нам пришлось возиться с определением коллизий, с тем, чтобы поле обзора между камерой и персонажем оставалось чистым, чтобы игрок всегда видел, что он делает.

Все эти ограничения обернулись для нас целой кучей проблем. Их было как минимум 50 штук, и я взял на себя смелость пронумеровать их для вашего удобства. С большинством этих проблем я столкнулся, работая над Journey, и, как правило, первое решение всегда было ошибочным. Некоторые из них остаются даже в выпущенных играх, и некоторые так и остались нерешёнными в Journey.

На самом деле сначала в этом списке было 100 ошибок, но пришлось его немного урезать, чтобы уложиться в регламент выступления.

#1 Использовать динамическую камеру без необходимости


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

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

#2 Использовать камеру, не подходящую к дизайну уровней


Дизайн уровней тесно связан с проектированием камеры. И уровень, и камера должны помогать игроку ориентироваться в игровом мире. Если вы знаете, под каким углом будет находиться камера, вы можете спроектировать весь уровень с учётом этого. Если же камера может менять своё направление, нужно быть уверенным, что камера органично перемещается по миру, указывая игроку верное направление. В то же время камера должна хорошо работать во всех типах локаций, которые есть в вашей игре: и в узких помещениях, и на открытых пространствах.

#3 Использовать глобальные координаты и кватернионы для описания положения камеры


Эта проблема касается, скорее, исключительно программной реализации поведения камеры. Можно предположить, что камера от третьего лица должна вести себя, как человек, держащий камеру в руках и поворачивающий её в разные стороны. Но дело в том, что в играх с видом от третьего лица, в отличие от игр с видом от первого, осью вращения является не камера, а игровой персонаж. И когда камера поворачивается, она должна совершать движение по орбите вокруг персонажа. Поэтому не так важно хранить глобальные (x, y, z) координаты камеры, потому что их всегда можно вычислить из координат персонажа.

Что касается кватернионов — считается, что ориентацию в пространстве лучше всего описывать при помощи них, и они действительно очень полезны. Но игроки не мыслят кватернионами, они мыслят углами Эйлера, а, значит, такими понятиями, как тангаж и рыскание. Для них понятнее поворачивать камеру влево-вправо и вверх-вниз при помощи аналоговых стиков или любого другого элемента управления. Так что лучше использовать углы Эйлера, чтобы описать ориентацию камеры, а, значит, использовать такие понятия как тангаж, рыскание и, возможно, крен.

Не обязательно использовать углы в конечных вычислениях, но они должны фигурировать в качестве входных данных, которые впоследствии можно перевести в кватернионы. Что касается описания положения камеры, то вместо глобальных трёхмерных координат лучше использовать расстояние от персонажа и отклонение по двум осям (если есть необходимость расположить персонажа не в центре экрана).

#4 Использовать такое расстояние от камеры до персонажа, при котором поле зрения может быть легко заслонено


Поле зрения по сути представляет собой воображаемую линию, соединяющую камеру и персонажа. Эта линия является ключевой частью всей логики, касающейся работы камеры, и большая часть программного кода занимается тем, что сохраняет поле зрения чистым.
Чем ближе камера к персонажу, тем менее вероятно нарушение чистоты поля зрения.

#5 Позволять препятствиям заграждать поле зрения по бокам


Чаще всего препятствия заграждают обзор, появляясь именно с боков экрана. И самый простой способ предотвращения этого — постоянная проверка рейкастом от персонажа к камере, не был ли заслонён персонаж. Если препятствие его заграждает, мы можем подвинуть камеру ближе к персонажу. Но если передвигать её мгновенно, это приведёт к резкой смене кадров, а частая резкая смена кадров приводит к нарушению правила 30 градусов. Это правило пришло из кинематографа и гласит, что при резкой смене кадров угол съёмки должен меняться минимум на 30 градусов. Это помогает избежать ощущения трясущегося изображения.

Поэтому гораздо приятнее, когда препятствие, которое грозит заградить поле зрения, заранее огибается камерой. Вы можете обнаружить такое препятствие, используя серию рейкастов, исходящих от персонажа под разными углами.
image
Как только один из рейкастов обнаружит препятствие, вы можете заранее начать сдвигать камеру так, чтобы препятствие не попало в поле зрения. При желании вы можете повторно использовать эти вычисления в последующих кадрах, чтобы облегчить работу процессора.

#6 Отодвигать камеру от препятствия, когда игрок пытается сдвинуть камеру в его сторону


Вот мы и подошли к первому конфликту в нашей модели поведения камеры.

В Journey и других похожих играх пользователь может управлять камерой при помощи аналоговых стиков на геймпаде. И очень важно, чтобы намерения игрока были для вашей игры на первом месте. Поэтому, если игрок хочет повернуть камеру в какую-то сторону, камера обязательно должна его слушаться, иначе он попросту начнёт злиться. И вот у нас возникла ситуация, когда камера пытается обойти препятствие, а игрок пытается камеру в это препятствие направить. В этом случае единственное возможное на мой взгляд решение — это приблизить камеру к игроку. Но так как мы уже заранее можем знать, что препятствие грозит попасть в поле зрения, а игрок пытается повернуть камеру как раз так, чтобы это препятствие точно попало в объектив, мы можем медленно приближать камеру к персонажу. Тогда, к моменту, когда препятствие должно будет попасть в поле зрения, камера будет находиться уже довольно близко к персонажу и оставит препятствие позади.

#7 Позволить игроку переместить камеру внутрь препятствия


Чтобы избежать этой ошибки, достаточно просто использовать сферический коллайдер вокруг камеры, чтобы не позволять камере входить внутрь игровых объектов.

#8 Позволять различным силам соперничать в праве на перемещение камеры


Мы уже рассмотрели случай, когда камера пытается избежать препятствия, а игрок пытается её в это препятствие направить. Но это не единственный случай, существует множество подобных ситуаций. Движение камеры должно удовлетворять сразу нескольким условиям, и если эти условия соперничают друг с другом, то может возникнуть ситуация, когда они экранируют действия друг друга, и мы получим не очень хороший результат.

Но мы можем организовать условия немного по-другому. Мы знаем, что у камеры всего семь степеней свободы: тангаж, рыскание, крен, расстояние от персонажа, смещение по двум осям и угол обзора. Поэтому мы можем организовать работу условий, основываясь на том, какие степени свободы для каких условий важны. В примере, рассмотренном ранее, оба условия касались тангажа камеры. В этом случае мы берём все условия, касающиеся определённой степени свободы, и приоритезируем их. Опять же, для примера ранее мы знаем, что ввод игрока имеет наивысший приоритет, поэтому мы позволяем ему двигать камеру в сторону препятствия.

#9 Не позволять узким препятствиям нарушать поле обзора


Сохранять поле обзора чистым важно, но бывают случаи, когда попытки избежать появления препятствия между камерой и персонажем принесут больше проблем, чем пользы. Это касается небольших узких препятствий, например, колонн. В этом случае лучше будет смотреться, если вы просто позволите камере пролететь мимо препятствия. Игрок всё равно сможет проследить за движением персонажа, несмотря на то, что тот будет ненадолго заслонён. Для этих целей можно разделить препятствия на те, которые могут заслонять персонажа, и те, которые не могут.

#10 Позволять камере пересекаться с препятствиями


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

#11 Воспринимать холмы как препятствия, которых нужно избегать


В Journey полно песчаных дюн с пологими склонами и, как и в случае с другими препятствиями, важно избегать их появления между камерой и персонажем. Однако, не стоит воспринимать холмы как препятствия, которые нужно огибать справа или слева, гораздо логичнее будет приподнять камеру над холмом. Что касается Journey, то там песчаные дюны не учитываются во время рейкастов. Но можно проверять направление нормали к той поверхности, что заграждает поле обзора, и по нему определять, стоит ли огибать препятствие сбоку, или лучше поднять камеру над ним.

#12 Сдвигать камеру вбок, когда препятствие появляется сзади


До сих пор мы рассматривали случаи, когда препятствие появляется сбоку, и камера отодвигается влево или вправо. Но препятствия могут появляться с совершенно разных сторон. Например, если персонаж двигается в сторону камеры, и камера двигается назад, может возникнуть ситуация, когда камера будет загнана в угол, и даже движения в стороны не смогут вывести её оттуда. Для предотвращения такой ситуации стоит использовать рейкаст, направленный назад от камеры, и при его помощи выяснять, нет ли позади неё препятствия, и, если оно есть, просто сдвигать камеру ближе к персонажу.

#13 Позволять ближней границе рендера камеры пересекать персонаж


Ближняя граница рендера (near clipping plane) — это техническое ограничение, свойственное всем камерам в трёхмерной графике. Всё, что находится ближе этой границы, обрезается, из-за чего в объектах могут появиться дыры. Нам нужно удостовериться, что персонаж редко оказывается ближе этой границы, а лучше — никогда. Поэтому между персонажем и препятствием всегда должно быть достаточно места для камеры, чтобы ближняя граница рендера не пересекала модель персонажа. Для этого достаточно сделать размеры коллайдера персонажа такими, чтобы персонаж никогда не приблизился к препятствию на расстояние, меньше критического.

#14 Использовать одинаковое расстояние для любых углов тангажа


image
Если вы смотрите вверх, камере необходимо опуститься вниз, чтобы персонаж остался в поле зрения. Но если мы опускаем камеру вниз, она достаточно быстро врежется в землю, если только вы не переместите её ближе к персонажу. В некоторых играх камера сначала врезается в землю, и только затем приближается. Но гораздо лучше сделать так, чтобы она начинала приближаться заранее, учитывая поверхность пола и следуя гладкой траектории. Также нелишним будет использовать подобную траекторию и в обратном направлении, чтобы в случае, если вы смотрите вниз, а камера поднимается над персонажем, расстояние до персонажа увеличивалось. Если вы смотрите вниз, то горизонт скрывается из поля обзора, вы видите только небольшой кусок пола вокруг персонажа, и вам может стать немного тесно. Но если расстояние до персонажа увеличить, то можно будет увидеть чуть больше пространства вокруг.

#15 Использовать одинаковые углы обзора для взгляда снизу и для остальных углов наклона камеры


Небо — оно большое. И было бы неплохо захватить как можно больше неба в объектив. В реальной жизни мы можем видеть почти всё небо сразу, используя периферийное зрение. Наш угол обзора вместе с периферией достигает почти 180 градусов. Чтобы дать игроку, смотрящему на небо в вашей игре, схожие ощущения, можно увеличивать угол обзора камеры по мере приближения её к земле. Это даст игроку ощущение того, что он смотрит на небо глазами своего персонажа.

#16 Изменять тангаж, дистанцию и угол обзора независимо друг от друга


Как мы уже говорили ранее, при изменении тангажа следует также изменять дистанцию камеры и угол обзора. Но если эти величины изменять независимо друг от друга, то мы столкнёмся с неприятным эффектом. Дело в том, что при изменении угла обзора, изменяются и размеры предметов на экране, так как угол обзора — это по сути зум. При изменении дистанции размеры предметов также будут меняться. При этом в нашем случае эти величины будут меняться в противоположных направлениях, и персонаж игрока, вместе со всеми остальными объектами на экране, начнёт судорожно менять свои размеры. Поэтому лучше сделать так, чтобы дистанция и угол обзора вместе зависели от тангажа, и изменялись тоже вместе. Однако, вы обязательно столкнётесь с ситуацией, когда какие-нибудь другие механизмы управления камерой также захотят менять дистанцию или угол обзора. В этом случае абсолютные значения этих величин можно сделать зависимыми от тангажа, а другим механизмам позволить менять относительный модификатор для нужных величин. Это могут быть как мультипликаторы, так и обычное прибавление-вычитание.

#17 Не сменять кадр, когда персонаж проходит через непрозрачную область


В этом случае угроза чистоты поля обзора находится спереди, что на самом деле происходит очень редко, потому что персонаж сам по себе имеет коллайдер, который не позволит ему пройти сквозь препятствие. Но бывают ситуации, когда препятствие является проходимым. Например, в Journey в роли таких препятствий выступают песчаные водопады. В этом случае единственное, что вы можете сделать — это резко сменить кадр.

#18 Изменять управление при резкой смене кадров


Когда вы наклоняете аналоговый стик вверх, это значит, вы даёте команду идти вперёд. Но направление этого «вперёд» зависит от направления камеры. И когда камера внезапно меняет направление при смене кадров, значение «вперёд» тоже резко меняется. При этом игрок не в силах моментально изменить положение пальца, ему нужно время, чтобы сориентироваться. Поэтому резкая смена кадров — это отличный повод использовать кат-сцену или какой-нибудь эффект перехода от одного кадра к другому. Или можно в момент, когда нужна смена кадра, поместить игрока в такую ситуацию, в которой ему ничего не будет угрожать. Кроме того, можно интерполировать значение «вперёд» между кадрами. Не уверен, хорошо ли это работает, но некоторые так делают.

#19 Нарушать чувство направления у игрока


Изменение управления — временная проблема, потому что игрок довольно быстро может адаптироваться к новым условиям. Однако, смена кадров с изменением угла съёмки влияет на игрока в более долгосрочной перспективе, нарушая его чувство направления. Игроки чаще всего используют два способа ориентирования в пространстве. Первый способ — это так называемое навигационное счисление, когда человек следит за своим изменением положения в пространстве. Например, если человек разворачивается на 180 градусов, он понимает что север теперь — это юг. Второй способ ориентации — по отличительным особенностям ландшафта и окружения в целом. При резкой смене кадров первый способ ориентации уже не работает — игрок не может знать, на сколько градусов повернулась камера, и поэтому не может повернуть воображаемую карту, чтобы сориентироваться. Поэтому важным фактом будет то, что камера должна показывать игроку различимые ориентиры либо какие-то другие объекты, которые позволят ему понять, где он сейчас находится, и не потерять чувство направления.

#20 Нарушать правило 180 градусов


Это широко известное в кинематографе правило, которое заключается в том, что при смене кадров нельзя изменять угол съёмки на 180 градусов. К счастью, в играх нам не приходится слишком часто волноваться по поводу этого правила, потому что смена кадров — это крайняя мера, прибегать к которой нужно, только если нет другого выхода. Но бывают случаи, когда это правило придётся кстати. Чаще всего это касается кат-сцен. Например, во время окончания кат-сцены камера должна показывать игроку достаточную для ориентирования информацию. Также можно после окончания кат-сцены медленно переносить камеру от исходного положения к игровому.

#21 Фокусироваться только на персонаже игрока


До этого мы говорили исключительно о персонаже, но игроку нужно видеть и другие объекты окружения, чтобы успешно ориентироваться в пространстве. Например, игроку нужно видеть землю непосредственно вокруг персонажа, чтобы знать, не врежется ли он в стену или не упадёт ли с обрыва. Также ему нужно видеть и более отдалённые объекты, например, горы на горизонте в Journey или персонаж другого игрока.

#22 Всегда полагаться на игрока в вопросе управления камерой


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

#23 Не изменять рыскание, когда игрок бежит


Простейший способ позволить игроку увидеть, куда он идёт, это развернуть камеру в направлении его движения. Просто возьмите направление движения игрока и примените его к углу рыскания камеры, чтобы она плыла вслед за персонажем. Но есть один нюанс — например, если игрок бежит по направлению к стене, нет никакой необходимости направлять камеру в стену. Поэтому стоит использовать скорость движения персонажа, чтобы определять направление его движения, а не направление стика геймпада. Тем более, если игрок, скажем, упёрся в невидимую стену, не стоит дразнить его, показывая, что за этой стеной находится, лучше просто развернуть камеру в нужную сторону, показывая игроку, куда ему следует идти.

#24 Препятствовать оценке расстояния


Проблема в том, что экран монитора — плоская поверхность. Но даже если бы у нас были трёхмерные дисплеи, глубина восприятия всё равно является плохим механизмом для оценки расстояний. Игроки гораздо лучше оценивают расстояния, находящиеся в плоскости дисплея. Например, если в вашей игре вид сверху, игрокам проще оценивать горизонтальные расстояния, а если сбоку — игроки могут оценивать вертикальное расстояние и горизонтальное по одной оси.

#25 Оставлять камеру в горизонтальном положении, когда персонаж достигает края обрыва


Когда человек подходит к обрыву, он обычно смотрит вниз, и камера должна делать точно так же. Для этого нужно сделать ещё один рейкаст, на этот раз направленный вниз непосредственно перед персонажем. И как только рейкаст обнаружит, что персонаж подошёл к обрыву, камера должна сдвинуться вверх и изменить тангаж так, чтобы угол съёмки позволял увидеть этот обрыв и положение персонажа относительно края. Дополнительным плюсом такого приёма является тот факт, что камера будет уже заранее готова к тому, чтобы обогнуть край, если игрок начнёт падать с обрыва. Если этого не сделать и оставить камеру в обычном положении, то при падении персонажа она последует за ним и сама врежется в край обрыва.

Публиковать сразу все 50 пунктов мне показалось излишним — статья получилась бы огромной. В скором времени появится вторая часть перевода.

© Habrahabr.ru