U
タブ 03カメラと入力6 レッスン — タップで開く
03 / 06 · 8 分
カメラと入力

Cinemachine とカメラの揺れ

ここまでのプロジェクト

Assets/

Scenes/

Arena.unity

CameraTargetCinemachineBrainCM vcamImpulse source / listenerOrbitCamera.cs→Cinemachine vcam

プロジェクトの設定

Cinemachine package

すでにあるものこのレッスンで追加このレッスンで置き換え

三段目、つまり最終段です。Cinemachine は FollowCamera と OrbitCamera の両方を、設定するだけの component に置き換えます。しかも壁抜け・減衰・カットの出来は、いま書いたコードより上です。

アニメーション図

回り込む発想は同じで、減衰・壁との衝突・ターゲットの構図がはじめから備わっています。

インストールと初期設定

  1. 1

    Window▸Package Manager▸Unity Registry → で Cinemachine を検索 → Install。

  2. 2

    GameObject▸Cinemachine▸Virtual Camera(Cinemachine 3 では CinemachineCamera)。

  3. 3

    Unity は Main Camera に CinemachineBrain を自動で追加します。この Brain が実際に本物のカメラを動かす側です。

  4. 4

    仮想カメラ側で Follow = Knight、Look At を Knight の CameraTarget に設定します。

頭の中のイメージ

  • 仮想カメラはカメラではありません。「ここに立って、あそこを、減衰はこのくらいで見る」という手順書です。

  • Main Camera の Brain が、有効な仮想カメラのうち Priority が最も高いものを選び、そこから滑らかに寄せます。

  • つまりカメラの切り替えは Priority を変えるか SetActive を呼ぶだけ。ブレンドは自動的に付いてきます。

二度のクリックで三人称の回り込みカメラ

  1. 1

    仮想カメラの Body を Third Person Follow にします(CM3 では Orbital Follow)。

  2. 2

    Camera Distance を 6、Shoulder Offset の X を 0.5、Damping を 0.3 / 0.3 / 0.3 に設定します。

  3. 3

    Camera Collision Filter に環境用レイヤーを指定すれば、壁を抜ける問題ここで片付きます。

  4. 4

    リグの向きがすでに正しければ Aim = Do Nothing、ターゲットを構図に収め続けたいなら Composer にします。

✓ Hand-written camera

仕組みが分かり、すべての行を自分で制御できます。小さなゲームなら向いています。

✓ Cinemachine

壁抜け、減衰、揺れ、カメラ切り替え、カットシーンがすべて解決済みで、実戦でも使われてきました。

Impulse でカメラを揺らす

  1. 1

    仮想カメラに Cinemachine Impulse Listener を追加します。

  2. 2

    爆発するものや攻撃を当てるものに、Cinemachine Impulse Source を追加します。

  3. 3

    コードから GenerateImpulse() を呼べば、射程内の Listener がすべて揺れます。

HitShake.cs
using UnityEngine;
using Unity.Cinemachine;      // Cinemachine 2: using Cinemachine;

public class HitShake : MonoBehaviour
{
    [SerializeField] private CinemachineImpulseSource source;

    public void Shake(float strength = 1f)
    {
        source.GenerateImpulseWithForce(strength);
    }
}

スキルやカットシーン用にカメラを切り替える

C# スクリプト
[SerializeField] private CinemachineCamera gameplayCam;
[SerializeField] private CinemachineCamera ultimateCam;

public void PlayUltimate()
{
    ultimateCam.Priority = 20;      // higher wins
    Invoke(nameof(BackToGameplay), 2f);
}

void BackToGameplay() => ultimateCam.Priority = 0;