🏃‍♂️

CinemachineのStateDrivenCameraを使ってみる

2021/08/15に公開

Cinemachineに「State-Driven Camera」というものがあります。
今回はこれを触っていきます。

概要

この機能はAnimatorに設定しているモーションとVirtualCameraの切り替えを対応付けできます。
カメラの切り替えはカメラをブレンドすることもできます。

上記のような感じのことができるのですが、今回はシンプルにIdleとWalkとJumbのモーション間の遷移のみに対応したVirtualCameraを設定して行います。

StateDrivenCamera作成

Cinemachineは初期では入っていないと思うので、PackageManagerでインポートしてください。入っている状態から説明します。

メニューのCinemachineの「Create State-Driven Camera」を選びます。

そうするとStateDrivenCameraとその子にVirtualCameraが1つできます。

StateDrivenCameraの設定

StateDrivenCameraのFollowとLookAt①に追従させたいキャラを設定し、AnimatedTarget②に対応付けさせたいAnimatorを設定します。

③のVirtualCameraChildrenの+をクリックするとVirtualCameraを増やすことができます。
今回は3つ分のカメラを用意したいので、もう2つ分増やします。

④のListにAnimatedTargetで設定したAnimatorのStateと対応付けしたいVirtualCameraを設定します。

VirtualCameraの設定

個別にVirtualCameraを設定していきます。

初期状態ではVirtualCameraはStateDrivenCameraで設定したFollowやLookAtが適用されるのですが、FollowOverrideとLookAtOverrideに設定すると上書きできます。

あとの設定は通常のVirtualCameraを設定するのとほぼ同じなので他の説明は割愛します。

Animatorの設定

キャラに設定するAnimatorにはキー操作SWADでWalkに遷移、キーを離すとIdleに戻り、IdleでSpaceキーを押すとJumpに遷移する設定をしました。
パラメータのspeedが0より大きい数値が設定されていればWalkに遷移、Walk時speedが0ならIdleに戻し、パラメータのトリガーjumpがONになればJumpに遷移するようなAnimatorを作りました。
Animatorは今回の本題ではないので詳しくは説明せず、設定の画像のみにします。


キャラ操作

キャラクター操作をするスクリプトはCharacterにComponent追加しています。
これもソースコードを載せるだけにします。

キャラクターを操作するクラス
using UnityEngine;

/// <summary>
/// キャラクターを操作するクラス
/// </summary>
public class MoveCharacterSimple : MonoBehaviour
{
  // Playerキャラモデル
  [SerializeField] private GameObject playerObject = null;

  // PlayerキャラのAnimator
  [SerializeField] private Animator playerAnimator = null;

  // 移動速度
  private float moveSpeed = 3f;

  /// <summary>
  /// Update処理
  /// </summary>
  private void Update()
  {
    // speedのパラメータに設定し、その値でWalkに遷移
    if (Input.GetKey(KeyCode.S))
    {
      transform.position -= transform.forward * moveSpeed * Time.deltaTime;
      playerAnimator.SetFloat("speed", moveSpeed);
      playerObject.transform.localRotation = Quaternion.Euler(new Vector3(0f, 180f, 0f));
    }
    else if (Input.GetKey(KeyCode.W))
    {
      transform.position += transform.forward * moveSpeed * Time.deltaTime;
      playerAnimator.SetFloat("speed", moveSpeed);
      playerObject.transform.localRotation = Quaternion.Euler(new Vector3(0f, 0f, 0f));
    }
    else if (Input.GetKey(KeyCode.A))
    {
      transform.position -= transform.right * moveSpeed * Time.deltaTime;
      playerAnimator.SetFloat("speed", moveSpeed);
      playerObject.transform.localRotation = Quaternion.Euler(new Vector3(0f, 270f, 0f));
    }
    else if (Input.GetKey(KeyCode.D))
    {
      transform.position += transform.right * moveSpeed * Time.deltaTime;
      playerAnimator.SetFloat("speed", moveSpeed);
      playerObject.transform.localRotation = Quaternion.Euler(new Vector3(0f, 90f, 0f));
    }
    // JumpにTriggerを設定し遷移
    else if (Input.GetKeyDown(KeyCode.Space))
    {
      playerAnimator.SetTrigger("jump");
    }
    // speedのパラメータを0に設定し、その値でIdleに遷移
    else
    {
      playerAnimator.SetFloat("speed", 0f);
    }
  }
}

まとめ

CinemachineのStateDrivenCameraを使った感想としては、Animatorに紐づくシンプルなカメラ切り替えは楽にできるなと思いました。

ただ、経過時間でとかイベントでとか色々条件を加えるとスクリプトとの連携が複雑になりそうなので、設計を考えてやる必要がでてきそうです。

とはいえ、可能性は感じることのできる機能でした。

Discussion