【Unity】Cinemachine Mixing Cameraで複数カメラをブレンドする

Cinemachineで複数のバーチャルカメラをブレンドする方法はないの~?

Cinemachine Mixing Cameraを使えば可能だわ!

Cinemachineには、複数のバーチャルカメラをブレンドしてグループ管理できるCinemachine Mixing Cameraがあります。

Cinemachine Mixing Cameraは一つのバーチャルカメラとして機能し、最大8個の子バーチャルカメラを指定したウェイトでブレンドすることができます。ブレンドは加重平均で行われます。

参考:Cinemachine Mixing Camera | Cinemachine | 2.6.0

本記事では、Cinemachine Mixing Cameraを用いて複数のバーチャルカメラ情報をブレンドする方法について解説します。

この作品はユニティちゃんライセンス条項の元に提供されています

動作環境
  • Unity2021.1.17f1
  • Cinemachine2.7.5

前提条件

事前にCinemachineパッケージがインストールされているものとします。

インストール方法が分からない方は以下記事をご覧ください。

【Unity】滑らかに(遅れて)追従するカメラを簡単に実装する方法
Cinemachineを用いてキャラクターを追従するカメラワークを実装する方法の解説記事です。 キャラクターを追従するカメラワークはスクリプトでも実装できますが、Cinemachineを使うことで次のメリットが得られます ...

次のようなシーンを例にCinemachine Mixing Cameraを適用していく形で解説していきます。

Cinemachine Mixing Cameraの設定

ヒエラルキビューの+ボタン(またはメニューのGameObject)をクリックし、Cinemachine > Mixing Cameraを選択します。

すると、シーンにCinemachine Mixing Cameraオブジェクトが配置されます。このとき、Mixing Camera配下に子バーチャルカメラが2つ置かれた状態になっています。

必要に応じて子バーチャルカメラを設定します。

例では、キャラを後ろから俯瞰するバーチャルカメラを3つ配置することとします。

追加された子バーチャルカメラのウェイトは0.5で初期化されます。

必要に応じて、CinemachineMixingCameraコンポーネントのChild Camera Weights項目のウェイト値を調整します。Mix Result加重平均されたウェイトの割合がバーで表示されます。

実行結果

各子カメラのウェイト値を変更すると、カメラ位置が変化していることが確認できます。

加重平均の計算

Cinemachine Mixing Cameraが子バーチャルカメラをブレンドするときに使う加重平均は次のような計算式になっています。

x = \frac{w_1 x_1 + w_2 x_2 + \cdots + w_n x_n}{w_1 + w_2 + \cdots + w_n}
w_iは子バーチャルカメラのウェイト、x_iは子バーチャルカメラ情報を表します。バーチャルカメラ情報とは、カメラのFOVや位置、向きなどの事です。内部的にはCameraState構造体の変数として保持されます。

参考:Struct CameraState | Package Manager UI website

ウェイトを掛けたバーチャルカメラ情報をウェイトの総和で割ることで、実質的に各ウェイトの総和が1になるような振舞いをします。

例えば、w_1 = 2, w_2 = 5, w_3 = 3のとき、

\begin{aligned}
x &= \frac{2 x_1 + 5 x_2 + 3 x_3}{2 + 5 + 3} \\
&= \frac{2 x_1 + 5 x_2 + 3 x_3}{10} \\
&= 0.2 x_1 + 0.5 x_2 + 0.3 x_3
\end{aligned}

となり、ウェイトの総和は0.2 + 0.5 + 0.3 = 1となります。

スクリプトから設定情報にアクセスする

Cinemachine Mixing Cameraは、CinemachineMixingCameraクラスのコンポーネントとして取得することができます。

var mixingCamera = vcamObject.GetComponent<CinemachineMixingCamera>();

クラスの詳細は以下公式リファレンスから参照できます。

参考:Class CinemachineMixingCamera | Package Manager UI website

本記事ではすべての機能を解説しませんが、いくつか主要なプロパティやメソッドを紹介します。

子バーチャルカメラの一覧を取得する

ChildCamerasプロパティから取得できます。

public CinemachineVirtualCameraBase[] ChildCameras { get; }

CinemachineVirtualCameraBase型の配列として返されます。例えば、子バーチャルカメラが3個の場合は長さが3の配列が返されます。

CinemachineVirtualCameraBase型はCinemachineバーチャルカメラを表す基底クラスです。

参考:Class CinemachineVirtualCameraBase | Package Manager UI website

子バーチャルカメラのウェイト値を取得する

GetWeight()メソッドから取得できます。

public float GetWeight(CinemachineVirtualCameraBase vcam)
public float GetWeight(int index)

引数にはインスタンス0始まりのインデックスで子バーチャルカメラを指定します。

取得に成功すると、指定された子バーチャルカメラのウェイト値が返されます。

子バーチャルカメラのウェイト値を指定する

逆にウェイト値を指定したい場合はSetWeight()メソッドで行います。

public void SetWeight(CinemachineVirtualCameraBase vcam, float w)
public void SetWeight(int index, float w)

第1引数には、インスタンス0始まりのインデックスで対象を指定します。
第2引数には、上書きするウェイト値を指定します。

サンプルスクリプト

Cinemachine Mixing Cameraの子バーチャルカメラのウェイトをスクリプトから書き換える例です。

ChangeWeightExample.cs
using Cinemachine;
using UnityEngine;

public class ChangeWeightExample : MonoBehaviour
{
    // Cinemachine Mixing Cameraコンポーネント
    [SerializeField] private CinemachineMixingCamera _mixingCamera;

    private void Awake()
    {
        // 子カメラの配列取得
        var children = _mixingCamera.ChildCameras;
        
        for (var i = 0; i < children.Length; ++i)
        {
            // ウェイトを適当に設定
            var weight = i + 1;
            
            // 子バーチャルカメラのウェイトを書き換え
            // 第1引数 : 子のインデックス(0始まり)
            // 第2引数 : 設定するウェイト値
            _mixingCamera.SetWeight(i, weight);
        }
    }
}

CinemachineMixingCamera.ChildCamerasプロパティより、子バーチャルカメラの一覧を配列で受け取ることができます。

CinemachineMixingCamera.SetWeight()メソッドでは、指定された子供のウェイトを書き換えます。

実行結果

スクリプトから設定した通りのウェイト値に書き換わっていることが確認できました。

さいごに

Cinemachine Mixing Cameraを用いて複数のバーチャルカメラを加重平均でブレンドする方法を解説しました。複数のバーチャルカメラをグループ化してブレンドできる便利な機能です。

これ以外にも様々なグループ管理が出来るバーチャルカメラが存在します。詳細は以下公式マニュアルよりご確認ください。

参考:Virtual Camera の制御とグループ化 | Cinemachine | 2.6.0

参考サイト