Бить в спину или не бить? Вот в чем вопрос!
Прелюдия
Сегодня поговорю о механике удара в спину. Суть ее в том, чтобы наносить повышенный урон при атаке противника вне поля его зрения. Ну, а так как люди, да и большинство гуманоидных существ не видят спиной, то и атака эта проводится сзади. В качестве примера будем рассматривать ситуацию с полусферами (полуокружностями, если захочется подушнить).
Процесс осознания
Один из самых дешевых (с точки зрения оптимизации) вариантов - это обнаружение источника урона по его позиции. Для этого берем два вектора:
- Первый - это "направление взгляда" цели. В кавычках, так как, скорее, будет использоваться вектор модели, смотрящий вперед, он же forward-вектор.
- Второй - это вектор от источника удара к цели.
Вспоминаем школьные правила. Угол между векторами лежит в диапазоне от 0° до 180°. Если вектора сонаправлены, то угол 0°. Если разнонаправлены, то 180°. Ну а если перпендикулярны, то 90°, соответственно.
Отсюда делаем вывод, что угол между forward-вектором цели и вектором от источника к цели в момент удара. Так как мы приняли, что считаем заднюю полусферу уязвимой, угол между векторами должен быть меньше 90°. Удар при этом производится из области, помеченной зеленым цветом на картинке.
А теперь обратим внимание на картинку с красной зоной. Что не так с красной полусферой? Если приглядеться, то она проходит по линии спины персонажа. С точки зрения игрока, именно там находится уязвимость противника.
Если наложить эти зоны одну на другую, получим неполное пересечение - отмечено желтым.
Желтая зона - это зона без вопросов. Она является местом "обоюдного согласия" игрока и игры по принципу нанесения урона. А вот с боковыми придется разобраться.
Зона зеленого цвета у правого плеча выглядит, как нечто нечестное по отношению к цели атаки. Направление атаки частично захватывает фронтальную часть модели, делая ее “более уязвимой” справа.
Зона красного цвета у левого плеча все делает с точностью до наоборот. Цель, с точки зрения игрока, уязвима, но попытка нанести критический урон проваливается.
Это приводит к одному занимательному паттерну поведения игрока, когда он нащупал, что кружить вокруг противника по часовой стрелке выгоднее ля нанесения критических атак, чем против часовой.
Как это лечить и надо ли?
Ниже будут варианты решения, который пришли в голову примерно за полторы секунды. А больше, как говорится, нам и не надо!
- Смириться с этим и не делать ничего. Игроки, правда, будут считать игру нечестной по отношению к ним. Особенно, это будет заметно в мультиплеерных проектах.
- Провести аудит поз моделей и понять, насколько меняется положение спины относительно фронтальной позиции. Если везде стоит левосторонняя поза, тогда проще считать угол со смещением на поправку от поз моделей. Это будет актуально для мультиплеерных шутеров, например. Конечно, можно заставить художников заставить переделать все модели, но они будут не рады вашему предложению.
- Закрепить на модели персонажа вектор, направленный перпендикулярно его спине. Это будет более честно по отношению к игроку и сведет его мироощущение с игровыми правилами. Также можно применять в мультиплеерных проектах, хоть и заставить реплицировать дополнительные данные.
- Реализовать механику через коллизии. Это очень опасная штука с точки зрения ошибок, но при должном навыке также устраняет проблему. Плюс от этой реализации в том, что она позволяет делать переменные зоны уязвимости. Например, атака в глаз упавшего на землю дракона.
- Комбинированный. Использовать решения выше в том или ином сочетании, в зависимости от потребностей и возможностей.
- Шуточный. Не делать 3D-игры, а только 2D с видом сбоку. Там точно всегда понятно, где спина.
Вы-воды
В итоге, такая простая механика вылилась в целую систему со своими внутренними правилами и нюансами.
Ну и напоследок, реализовал третий вариант с вектором в спине, от которого будем брать только ротацию по оси, направленной вертикально вверх (проекция на горизонтальную плоскость "земли" нам нужна, если простым языком).