いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

UnityでCinemachineのバーチャルカメラを使う

バーチャルカメラというのを使ってみました。ゲームで、例えば主人公が動くのを後ろからカメラが追いかけ、立ち止まるとカメラがビューンと動いて(背景もダイナミックに変化!)正面からアップに……みたいな演出がありますよね。いわゆる「カメラワーク」というやつで、理屈を言えば空間内でカメラを主人公を撮りながら動かせばよいだけです。しかしこれを実際にやろうとすると結構な仕事になります。それなりにコードを書かなければなりません。それを割と簡単に実現する方法があるのです。

CinemachineというアセットをUnityにインストールします。導入の仕方を丁寧に解説しているサイトがたくさんあり、助かりました。で、実際に使ってみると……よく分からないというか、なかなか思いどおりにいきませんでした。が、実験を繰り返してどうやら「ゲームに使えるかな?」という感じになったので記録しておきます。

 

バーチャルカメラをシーンに配置し、インスペクタを見てみます。Follow、Look Atという項目があります。ここには配置されているオブジェクト(主人公とか、Cubeとか、……)を入れます。意味は次の通り。

Follow……カメラがオブジェクトに追従
LookAt……カメラがオブジェクトを注視

追従というのはセットされたオブジェクトについて回る、ということです。

 

●ひとつのバーチャルカメラを使用

LookAt、Followに同じオブジェクトを入れておき、Body、Aimという項目を以下のようにセットする。3通り試しました。
①BodyをTransposer、Aimを空(Do nothing)にする……カメラはオブジェクトに追従
②BodyをTransposer、AimをComposer……カメラは追従、オブジェクトを向く
③Bodyを空、AimをComposer……カメラは固定、オブジェクトを向く
カメラを追従させたければFollowの欄にオブジェクトを入れるだけでなく、Bodyに「tranposer」をセットしなければなりません(そうしないとカメラが動きませんでした)。また、①、②は今回の実験では区別がつきませんでした。その他のパラメータをいじったときに何か効果があるのかも知れませんが。Aimに「composer」をセットすると、カメラが常にオブジェクトを向くようにできるらしいです。実際、③でAimを空にすると単に固定されたカメラで撮影しているだけになります。写真を載せます。背景と球は動かさず、立方体を動かしています。

 

①、②では次のような感じです。カメラは立方体を追いかけ、向きは常に立方体を画像の真ん中に捉えるよう、調整されていることが分かります。もちろんそれに伴い、動かしていない背景も球も位置が変化して映ります。

③では次の通り。カメラの空間内の位置は変えず、向きだけを変えて立方体を画面の中央に捉えています。

 

●2つのバーチャルカメラを使用

シーンにバーチャルカメラを2つ配置します。そしてバーチャルカメラ1のLook AT、Follow、バーチャルカメラ2のLook AT、Followに同じオブジェクトを入れておきます(4ヶ所に同じオブジェクトを入れる)。2通り試しました。

・カメラ1でBodyをtransposer、Aimをcomposer

       ……カメラは追従、オブジェクトを向く。
・カメラ2でBodyを空、Aimをcomposer

       ……カメラは固定、オブジェクトを向く。

・カメラ1でBodyを空、Aimをcomposer

    ……カメラは固定、オブジェクトを向く。
・カメラ2でBodyを空、Aimをcomposer

    ……カメラは固定、オブジェクトを向く。

①では、カメラ1はオブジェクトに追従しますがカメラ2は決まった位置から撮ります。カメラのインスペクタにはPriority(優先度)という項目があり、大きな数値が入っているカメラが撮った画像が表示されます。スクリプトで優先度を変更すると、高い優先度のカメラの画像が表示されるようになりますが、「パッ」と変わるのではなく、カメラの位置がジワッと変化する感じでプロっぽい演出です。②ではどちらのカメラもカメラ位置を固定としています。こういう組み合わせも可能です。

 

優先順位を変更するコードは次の通りです。

GameObject vc1 = GameObject.Find("VirtualCamera1");

GameObject vc2 = GameObject.Find("VirtualCamera2");
としておき、
vc1.GetComponent<CinemachineVirtualCamera>().Priority = 5;
vc2.GetComponent<CinemachineVirtualCamera>().Priority = 10;
でオーケーです。

 

カメラを2つ使う場合、他の組み合わせとして「カメラ1もカメラ2もオブジェクトに追従」というのがありそうですが、「追従」というのはオブジェクトから決まったオフセット(位置のずれ)にカメラが常に配置されることで、従ってカメラ1、2は同じ位置にセットされてしまいます。これではカメラを2つ用意する意味がありません。だからなのか、このとき無理矢理カメラ2を1から引き離そうとしても戻ってしまいます。カメラ毎にオフセットを調節できるかも知れませんが、「もういいや」と実験もここまでに。なお、画像の2つのボタンはカメラの優先度を変更するために使いました。

(これに関して、最後の注を参照してください)

 

今度は3Dのゲームを書く予定なので、この機能も使ってみたいです。

 

追記:

カメラの追従の位置(オフセット)は Body の中のパラメータでセットできます
2024年5月8日(水) 

 

(注)この実験では2つのバーチャルカメラのBodyのオフセットに同じ値を入れています。どちらのカメラも対象のオブジェクトに対し同じオフセットの位置にいる、ということです。追記で書いたように、オフセットをカメラによっていろいろ変えられますので試してみてください。