適当おじさんの適当ブログ

技術のことやゲーム開発のことやゲームのことなど自由に雑多に書き連ねます

2D環境でState Driven Cameraを使った時のメモ

はじめに

Cinemachineが提供するカメラの1つで、その名の通り State(状態) を持つカメラです。State ごとに Virtual Camera を割り当てておくと、Stateに合わせて対応するカメラに自動で切り替えてくれます。自分のタイミングやある条件に基づいてカメラを切り替えたい場合に役に立ちそうです。とりあえず使ってみたので、そのときのメモを記事として残しておきます。

ちなみに、Cinemachineを2D環境で使ってみた際の記事はこちらにあります。Cinemachine?Virtual Camera?という方はこちらもどうぞ。

www.subarunari.com

デモ

最終的にこんな感じになりました。待機/徒歩、ローリング、アピールの3つの状態に合わせて異なる設定のカメラを切り替えています。詳細は次の章から説明していきます。

f:id:subarunari:20180521233437g:plain

State Driven Camera で必要なこと

状態の管理には、Animator の State Machine を使用します。基本的に State Machine を作って、それをカメラに割り当てるだけです。一応タイトルに2Dとつけましたが、3Dでもやることは基本的に変わりません。

  1. State Machine を作成する
  2. State Driven Camera を作成する
  3. 個々のVirtual Cameraの設定をする
  4. Stateを切り替えるようなスクリプトを作成する

この記事では、アニメーションのための Animator を使う方法を記載しています。カメラの状態を管理するためだけの State Machine でもやることは変わりありません。アニメーションのためのSpriteが必要ないくらいの違いしかないでしょう。

State Machineを作成する

今回はキャラクターのアニメーションとカメラを連動させるので、まずはアニメーションの State Machine を作成します。以下のような4つのアニメーションをパラメータによって切り替える State Machine を作成しました。

f:id:subarunari:20180521161614p:plain

「それぞれのアニメーションに対応するBool型のパラメータが存在し、Trueにすると対応する状態へ、FalseにするとWaitに戻る」 という作りです。アニメーションを必要としない場合は、「Create State > Empty」 で State をガシガシ追加して State Machine を作ればOKです。最後に作成した Animator をキャラクターに割り当てておきます。

State Driven Cameraを作成する

State Driven Camera は、 メニューバーの「Cinemachine > Create State-Driven Camera」を選択することで作成できます。手動で「CinemaChineStateDrivenCamera」コンポーネントをGameObjectにアタッチしてもらってもOKです。

f:id:subarunari:20180521161835p:plain:w240

メニューから選択すると、「CM StateDrivenCamera1」 というオブジェクトが作成されます。デフォルトで、1個のVirtual Camera を子オブジェクトとして持っています。

f:id:subarunari:20180521162424p:plain

State Driven Camera では子オブジェクトのVirtual Cameraを状態に合わせて切り替えていきます。したがって、取りうる状態の数だけ Virtual Camera を作成し、設定する必要があります。

子Virtual Cameraを追加する

今回は、以下の表のような状態が全部で考えられます。Wait/Walk, Rolling, Appeal 用の3つの異なるカメラが必要そうです。

State カメラの演出
Wait 遅延なしでキャラクターに追従する
Walk Waitと同じとする
Rollling 転がっている疾走感を出すためにカメラを遅延ありで追従させる
Appeal かわいい姿がよく見えるようにアップにする

State Driven Camera の子オブジェクトとして Virtual Camera を作成すると、自動的に Virtual Camera Children の項目にカメラが設定されていきます。カメラを複製し、状態名を含むように名前を変更し、最終的に以下のようになりました。

f:id:subarunari:20180521163154p:plain

StateとVirtual Cameraを対応づける

まず、State Driven Camera の 「Animated Target」 の項目に、Animatorを設定します。次に、「+」ボタンから Virtual Camera を追加し、Animatorの State と Virtual Camera を対応づけていきます。

f:id:subarunari:20180521233752p:plain

Animatorが設定されていないと、Stateの項目は (default) だけになります。ちなみに、 (default) は明示的に指定されていない State の場合に使われるカメラです。 今回は最終的に以下のような設定となりました。

f:id:subarunari:20180521233826p:plain

いくつかパラメータをピックアップして説明します。

  • Default Blend
    • 指定したイージングと秒数は、カメラ切り替え時に使用されます。
    • 「Cut」を指定すると、カメラ切り替え時にアニメーションせずにサッと切り替わります。
  • Wait
    • 指定した秒数だけ、現在のカメラへの切り替えを遅延させます。
  • Min
    • 指定した秒数だけ、次のカメラへの切り替えを遅延させます。

WaitとMinが若干ややこしいです。「ある状態ではカメラ切り替えを必ず遅延させたい」という場合は、Wait を使用します。「AからBに状態遷移した時だけ遅延させたい」という場合は、Aの Min に秒数を指定します。Bの Wait に秒数を指定してしまうと、他の状態からBに遷移したときも遅延してしまうためです。図にすると以下のような感じです。

f:id:subarunari:20180522150854p:plain

当然ながら WaitMin の両方を指定した場合は、合計した秒数遅延します。今回はいずれも 0 のままとしているので、遅延なく状態遷移と同時にカメラは切り替わります。

子Virtual Cameraの詳細設定

Virtual Cameraの設定内容は人によって異なりますが、参考までに載せておきます。

WalkCamera

待機時と歩いている時のカメラです。Dead Zoneはなくてもよかったのですが、少しだけ遊びを持たせたかったので設定しました。基本的にキャラクターに遅延なく追従させるために、DampingやLook Aheadはすべて 0 としています。

f:id:subarunari:20180522161113p:plain

RollingCamera

ローリングしたときに使われるカメラです。Dead ZoneをSoft Zoneいっぱいに広げています。カメラの追従を遅れさせることで、ローリング時の疾走感を演出してみました。

f:id:subarunari:20180522161506p:plain

冒頭のデモでは、ローリング後、画面中央にキャラクターが写るようにカメラが移動しています。これは、ローリング終了後にWalkCameraへと切り替えているためです。

AppealCamera

アピールしたときに使われるカメラです。Orthographic Sizeを 0.75 と他よりも小さめにしています。小さめにしておくことで、Orthographic Size が大きいカメラから切り替わった時に自然とズームされるようになります。

f:id:subarunari:20180522162655p:plain

Soft Zone, Dead Zone, Damping, Look Aheadなどはすべて 0 に設定しています。

Animatorを切り替えるスクリプトの作成

最後に、AnimatorのStateを切り替えるスクリプトを作成します。今回はスクリプトの詳細は記載しません。あるAnimatorのBool型のパラメータの値を切り替える場合は、以下のようなコードを実行します。このコードを、キャラクターにアクションさせる際に実行しています。

GetComponent<Animator>().SetBool("パラメータ名", 真偽値);

実際は都度 GetComponent<T>() が呼び出されるのを防ぐために、Awake() のタイミングで GetComponent<T>() したものを変数に確保しておき、その変数に対して SetBool を呼び出しています。

おわりに

以上、State Driven Cameraを使ってみたときのメモでした。うまく使えば、キャラクターのアニメーションとカメラワークを連動できて便利そうです。アニメーションと連動しない場合も、特定の条件下でカメラをバシバシ切り替える場合に役に立ちそうです。自分でVirtual Cameraを切り替えるためのコードを書かないでいいのは助かります(AnimatorのStateを切り替えるコードは必要ですが)。

カメラの切り替えとアニメーションの実行タイミングを別々にしたい場合は、AnimatorのState Machineをそのまま使わない方が都合が良いかもしれません。アニメーションの実行は遅延できないので、「ズームが完了してからアピールのアニメーションをする」といったことができないためです。

今回は局所的な例となってしまったので、もっと様々なシーンで使ってみて良い感じの使い方を調べていきたいと思ってます。