Как починить горизонтальный FOV в Unreal без ломания камеры — Game Design Radar
← Все посты

Как починить горизонтальный FOV в Unreal без ломания камеры

15.12.2025
Как починить горизонтальный FOV в Unreal без ломания камеры

Автор разбирает техническую проблему Unreal Engine: движок фиксирует горизонтальный FOV и масштабирует его через аспект вьюпорта. Это приводит к некорректному поведению при смене соотношения сторон (ультраширокие, 4:3 и т.п.). В данном фрагменте статьи описан способ исправить это через собственный подкласс камеры и корректную математику FOV.

Подкласс камеры

Создаётся обёртка над ACameraActor:

UCLASS() class AMyCamera : public ACameraActor { };

Цель — подменить тип компонента камеры внутри актёра, чтобы контролировать расчёт обзора.

Автор отмечает неудобство разделения логики между компонентом и актёром камеры в Unreal:

  • PlayerController и CameraManager по-разному работают с компонентами камеры, встроенными в разные типы актёров.
  • У CineCamera часть функционала (например, Look at Tracking) живёт в актёре, часть — в компоненте, поэтому при встраивании компонента без обёртки часть возможностей теряется.

Математика FOV и аспект

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

  • перевести угол в радианы,
  • взять половину угла, посчитать tan(halfAngle),
  • умножить/поделить тангенс на аспект,
  • обратно восстановить угол через atan и перевести в градусы.

Автор оборачивает FMath::RadiansToDegrees и FMath::DegreesToRadians в макросы R2D и D2R, чтобы упростить код.

Получение корректного аспекта

Функция CameraUtil::CalcAspectRatio(UWorld* W) должна возвращать реальное соотношение сторон. В примере по умолчанию возвращается 16:9 как fallback, если нет вьюпорта. В рабочем коде автор:

  • берёт аспект не с экрана, а с Local Player,
  • тем самым учитывает split-screen мультиплеер (предполагается, что все сплиты имеют один и тот же аспект, поэтому достаточно смотреть на первого игрока).

Инъекция компонента камеры

В конструкторе AMyCamera используется «магическое» DI-решение: через имя члена "CameraComponent" подменяется тип подкомпонента камеры на нужный (аналогично тому, как можно заменить CharacterMovementComponent в наследниках Character).

Альтернатива: CameraModifier

Если нельзя контролировать подкласс CameraActor, можно использовать CameraModifier и в нём пост-обработать DesiredView тем же кодом перерасчёта FOV. Автор считает этот путь более неудобным в типичном воркфлоу и поэтому не использует его как дефолт.

Выводы

  • Корректный перерасчёт FOV при смене аспекта требует работы с тангенсом половины угла, а не с самим углом.
  • Лучше создать собственный подкласс ACameraActor и подменить тип компонента камеры через конструктор.
  • Аспект-рейшо нужно брать с Local Player, чтобы корректно поддерживать split-screen.
  • Если нельзя менять тип актёра камеры, можно применить тот же код через CameraModifier, но это менее удобно.
check_circle Факт-чекинг
Статья прошла проверку. Фактологических ошибок не выявили.