lenec ru

← все посты

Cinemachine на практике: камера, которая не вызывает желания выключить игру

11K

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

Опираюсь на Unity 6 (6000.x), Cinemachine 3.x. В CM 3 поменялся API относительно CM 2 — туториалы из 2021 года могут вводить в заблуждение.

Что такое Cinemachine и зачем

Cinemachine — это система виртуальных камер. Вместо одной Main Camera, которую ты двигаешь скриптом, у тебя десяток CM Camera — каждая со своими правилами слежения, и одна реальная камера, которую Cinemachine Brain переключает между ними.

Главная идея: вместо «программирую движение камеры» ты «настраиваю поведение в инспекторе». Дизайнер может править параметры, не дёргая программиста.

Что Cinemachine даёт из коробки:

  • Follow + Look At с разными алгоритмами (Hard Follow, Smooth, Damping, Framing).
  • Гладкие переходы между виртуальными камерами (Cut, Ease In/Out, Custom Blend).
  • Confiner — ограничение зоны движения камеры коллайдером.
  • Collider — отталкивание камеры от препятствий.
  • Impulse Source — единая система камера-шейков.
  • Splines, dolly tracks для проездов.
  • 3rd Person, Free Look, Top Down — preset'ы под жанры.

Базовое: Cinemachine Brain + одна виртуальная камера

Минимальная сетка:

  1. На Main Camera — компонент CinemachineBrain.
  2. Создать CinemachineCamera в сцене (правый клик в иерархии).
  3. Указать в ней Tracking Target = transform персонажа.
  4. В компонентах CM Camera выбрать CinemachinePosition = Follow и CinemachineRotation = Composer.

Camera следует за персонажем с заданным offset'ом, плавно поворачивается на цель. По умолчанию параметры мягкие, без особой возни — уже работает.

Когда несколько CM Camera, активной считается с наивысшим Priority. CM Brain переключается на ту, у которой priority выше. Это позволяет делать переходы (катсцена → возврат) без скриптов:

_cutsceneCamera.Priority = 20; // включаем катсцену
// ...
_cutsceneCamera.Priority = 0; // возвращаемся к main

Tracking: Hard Follow vs Smooth vs Framing

В компоненте CinemachinePosition выбираешь алгоритм:

Hard Follow

Камера жёстко привязана к offset'у от target'а. Никакого сглаживания. Подходит для топ-даун игр или строгих фиксированных видов.

Smooth Follow

С damping'ом — камера догоняет цель. Параметры X Damping, Y Damping, Z Damping. Чем выше — тем мягче, но тем больше задержка.

Для платформера типичные значения: X=0.5, Y=0.3, Z=1.0. Для шутера от третьего лица — X=0.1, Y=0.1, Z=0.5 (быстрее реагирует).

Framing Transposer / Position Composer

Самый умный режим. Указываешь, в какой части экрана должен быть target (например, по центру по горизонтали и в нижней трети по вертикали для платформера). Камера двигается так, чтобы target оставался в этой зоне.

Дополнительные параметры:

  • Dead Zone Width/Height — зона, в которой target может двигаться без движения камеры. Для платформера маленький, для open-world — больше.
  • Soft Zone Width/Height — зона мягкого реагирования.
  • Lookahead Time — камера предсказывает движение target'а. Для платформера 0.3–0.5, чтобы видеть, куда бежишь.

Я почти всегда использую Framing/Position Composer. Lookahead делает камеру «умной» бесплатно.

Look At: Composer и Group Composer

Аналогично есть Rotation: Hard Look At, Composer, Group Composer.

Composer

Цель удерживается в указанной части экрана. Хорошо для шутеров от третьего лица — герой в нижнем-левом, простор для прицела по правой части экрана.

Group Composer

Несколько объектов как target. Камера сама подбирает расстояние и угол, чтобы все были в кадре. Используется в файтингах и кооп-играх.

var group = gameObject.AddComponent<CinemachineTargetGroup>();
group.AddMember(player1.transform, weight: 1f, radius: 1f);
group.AddMember(player2.transform, weight: 1f, radius: 1f);
_cmCamera.LookAt = group.transform;

Collider: камера и стены

Очень полезный компонент, который часто забывают добавить. CinemachineCollider (или Camera Decollider в CM 3) проверяет, не упёрлась ли камера в препятствие, и сдвигает её ближе к цели.

Параметры:

  • Avoid Obstacles — обнаружение коллизии.
  • Distance Limit — насколько близко может подойти к цели.
  • Damping When Occluded — скорость возврата на дистанцию после очистки обзора.

На 3D-проектах без Collider'а камера регулярно «уезжает» внутрь стен, и пользователю плохо видно героя. Collider закрывает 90% таких сценариев.

Импульсы: камера-шейк, не нужен скрипт

Камера-shake без Cinemachine — это собственный compute через AnimationCurve, скрипт на каждой пушке, ручная синхронизация. С CM Impulse — две настройки.

На источнике взрыва/выстрела добавляешь CinemachineImpulseSource. Настраиваешь форму волны (Bump, Recoil, Rumble) и амплитуду. В коде:

[SerializeField] private CinemachineImpulseSource _explosionImpulse;

private void Explode()
{
    _explosionImpulse.GenerateImpulse();
}

На CM Camera — компонент CinemachineImpulseListener. Он подхватывает все импульсы в зоне и применяет к камере. Один раз настроил — все взрывы автоматом трясут картинку.

Можно ограничить ImpulseSource радиусом: дальние взрывы не трясут камеру так сильно, как близкие. Реалистично и без ручной возни.

Confiner: камера в границах уровня

В платформерах и top-down играх часто нужно ограничить зону камеры — чтобы она не показывала «за пределами уровня». CinemachineConfiner2D (для 2D) или CinemachineConfiner3D делают это через Polygon Collider.

Создаёшь GameObject с PolygonCollider2D, рисуешь форму уровня, передаёшь его в Confiner на CM Camera. Камера будет двигаться только внутри полигона.

На больших уровнях с разными зонами — несколько Confiner'ов на разные CM Camera, переключаешь по триггеру входа в зону. Boss-арена сужает обзор, обычная зона — широкая.

Cinemachine + Timeline: катсцены без боли

Catscene workflow в CM:

  1. В Window → Sequencing → Timeline создаёшь Timeline asset.
  2. В нём — Cinemachine Track.
  3. На track перетаскиваешь несколько CM Camera, формируя последовательность shot'ов.
  4. Между ними — переходы (cross-fade'ы или жёсткие cut'ы).
  5. В коде запускаешь PlayableDirector.

На том же Timeline — анимации, аудио, активация/деактивация объектов. Получается полноценный cutscene-инструмент, и режиссёр может сидеть в Unity и править кадр за кадром.

Совет: каждая CM Camera для cutscene — отдельная нода в иерархии, с понятными именами (CamShot01_Hero_Closeup, CamShot02_Wide). Через год будешь спасаться.

Free Look: 3rd person camera

Самый частый паттерн в action-играх — orbit-камера, которая ходит вокруг героя по сфере, реагируя на мышь/стик.

CinemachineFreeLook делает это из коробки. Три rig'а (Top, Middle, Bottom) — камера интерполирует между ними по вертикальному вводу. Каждый rig — это orbit с радиусом и высотой.

Настройки, которые матчат:

  • X Axis: input от мыши/правого стика, скорость поворота. Обычно 300–500 для мыши, 250 для геймпада.
  • Y Axis: тангаж. Лимиты обычно от 0.1 до 0.9 (избежать пол и потолок).
  • Recenter to Target: автоматический поворот за движением героя. Полезно для adventure-игр, не нужно для шутеров.
  • Common Lens: одно поле зрения для всех rig'ов. Иначе при переходе между top/bottom у тебя зум скачет.

Когда Cinemachine — не лучший выбор

  • VR. Камеру в VR двигать нельзя (по крайней мере, не по yaw'у — игрок укачается). Cinemachine для VR подходит ограниченно: только для cutscene, и желательно с явным fade'ом.
  • Top-down strategy. Тут проще написать ручное движение по WASD/мыши, чем настраивать CM Free Pan.
  • 2D платформер с очень специфичной логикой (квадратные shot'ы как в Celeste). CM работает, но нужно фактически написать кастомный extension.

Расширения: пишем свои Behaviour

В CM есть extensibility через CinemachineExtension. Свой компонент, который изменяет поведение камеры. Пример: камера, которая немного отдаляется при низком HP игрока, чтобы показать угрозу.

[ExecuteAlways]
public class HealthZoom : CinemachineExtension
{
    [SerializeField] private Transform _player;
    [SerializeField] private float _maxZoomBack = 2f;

    protected override void PostPipelineStageCallback(
        CinemachineVirtualCameraBase vcam,
        CinemachineCore.Stage stage,
        ref CameraState state,
        float deltaTime)
    {
        if (stage != CinemachineCore.Stage.Body) return;

        var hp = _player.GetComponent<Player>().HealthPercent;
        var offset = (1 - hp) * _maxZoomBack;
        state.RawPosition -= state.RawOrientation * Vector3.forward * offset;
    }
}

Это очень мощно: ты получаешь доступ к pipeline камеры в нужной фазе и меняешь state. Без скриптов на самом GameObject камеры.

Что я обычно настраиваю в каждом проекте

  • Один CM Camera в основной gameplay-сцене, с Position Composer и Lookahead 0.4.
  • Один CM Collider, чтобы не зарывалась в стены.
  • Confiner на 2D-проектах.
  • Импульсы для всех hit-событий и взрывов.
  • Отдельные CM Camera для cutscene, dialogue zoom, kill cam.
  • Settings asset (CM Settings) с дефолтным Damping и FOV для всех камер сразу.

Что не делать

  • Не двигай Main Camera напрямую при включённом CM Brain. Cinemachine сразу отзовёт твоё изменение в следующий кадр.
  • Не клади 50 CM Camera в одну сцену. Переход с priority работает, но логика становится непрозрачной. Группируй через Timeline или скрипты-менеджеры.
  • Не забудь Disabled на неактивных камерах в больших сценах. Активные CM Camera обновляются каждый кадр, даже если не показывают на экран.
  • Не настраивай Damping выше 1.5 без причины. Это уже не «мягкость», а «лаг», который игроки чувствуют.

Что почитать

Документация Cinemachine на docs.unity.com — стартовая точка. Серия видео Cinemachine 101 от Unity на YouTube — старые, но базовые концепции не изменились. Adam Myhill — главный разработчик CM, его доклады на Unite (особенно 2018 года) объясняют, почему так сделано.

Главный приём, который я для себя вывел: проектирую камеру до того, как ставлю CM. Сначала на бумаге решаю, как выглядит кадр в gameplay'е (где герой, где UI, какой FOV). Потом подбираю CM-настройки под этот кадр. Если делать наоборот — крутить параметры наугад — потеряешь дни.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.