Third person Smooth Camera
Реализация плавной Third person камеры для Unreal Engine 4.
Всем привет! Начав работу над своим новым проектом, достаточно быстро обнаружилась потребность в улучшении работы стандартной Third Person камеры. К основным минусам которой можно отнести:
Резкая смена ракурса с ближнего на дальний в отсутствии коллизии у камеры
Стандартная камера резко "прыгает" от ближнего ракурса на дальний, что отрицательно сказывается на ощущении от игрового процесса.
Отсутствие механизма для контроля Spring Arm положения
Камера всегда стремится в начальную координату Spring Arm при сокращении дистанции. В общем случае это приводит к влетанию камеры внутрь геометрии персонажа. В современных играх, например God of War, Uncharted 4 и т.д. при критическом расстоянии и отсутствии места для размещения камеры между стеной и персонажем, камера поднимается над головой персонажа. Т.о. не перекрывается ракурс и остаётся некоторая видимость ситуации для игрока.
Итак, основные две задачи которые нужно было решить:
- Камера должна плавно менять ракурс от ближнего на дальний
- Плавно подниматься над головой персонажа при сокращении дистанции
Посмотрев другие решения, в которых использовался Timeline для плавной интерполяции длинны Spring Arm и даже двойная камера, одна из которых использовалась как proxy, я пришел к выводу, что они по моему мнению, несколько избыточны или же выглядят не оптимально для использования в реальном проекте. Я решил упростить и сделать максимально простую быструю для переноса реализацию плавной камеры.
Моё решение состоит из нескольких моментов:
1) Проверка на столкновение камеры с геометрией. Реализовано с помощью SphereTraceByChannel. Начальной координатой служит центр капсулы персонажа. Конечной координатой - вектор направления камеры полученный из поворота контроллера помноженный на текущую длину Spring Arm:
2) Если коллизия имеет место быть, то выбираем в качестве актуальной длины Spring Arm - длину между точкой столкновения и центром от капсулы персонажа.
Если камера ни с чем не сталкивается, то берём заданную длину для Spring Arm, которая используется для нормального игрового ракурса. В данном примере значение равно 300 и хранится в переменной InGameArmLenght.
3) Полученное значение сглаживаем каждый кадр с помощью FinterpTo между текущим и целевым и сохраняем в переменную ResultArmLenght.
Текущее - то которое было на предыдущем кадре. Т.о. если на текущем кадре камера ни с чем не сталкивается, то целевое значение длины SpringArm станет равно 300, соотв. будет плавный откат камеры назад от текущего меньшего значения до 300.
Задача No. 1 решена.
4) При помощи MapRange мы пересчитываем текущее значение длины Spring Arm в диапазон для смещения центра Spring Arm вверх. Диапазон имеет границы от стартового значения Z координаты для Spring Arm (заносится на старте в переменную InGameArmRelativeLocation) до значения половинчатой высоты капсулы, которое можно получить из самой капсулы.
Т.о. чем ближе камера к персонажу, тем она стремится выше подняться за счёт сдвига положения SpringArm по оси Z вверх.
Задача No. 2 решена.
В самом минимальном приближении камера будет находиться над головой персонажа оставляя игроку актуальный ракурс для игровой ситуации:
5) Блокировка полёта камеры из нижнего положения. Примерные углы для контроллера по pitch для нижнего ракурса камеры будут: 40...60 градусов.
Т.о. в данных углах и при наличии коллизии камеры с нижней поверхностью (полом) камера пролетает в геометрию персонажа, т.к. стремится поднять Spirng Arm по Z координате.
Чтобы решить это небольшое неудобство, достаточно добавить к текущей длине SpringArm (при наличии коллизии у камеры) дополнительное значение в зависимости от поворота контроллера при помощи ClampAngle в диапазоне от 0 до половинчатого значения размера капсулы по высоте.
В результате смотреть снизу мы можем, но камера теперь не стремится пролететь в персонажа:
Безусловно я не претендую на 100% правильность и единственность решения подобной задачи, тем не менее данная реализация вполне может послужить хорошей отправной точкой.
Проект доступен на моём GitHub в версии для Unreal Engine 4.23.
Всем хороших игр!