【Unity】Cinemachineで簡単にカメラの切り替えと揺れを作る

投稿者: | 2023-07-11

Cinemachineを使って、一人称カメラとフリールックカメラを簡単に切り替えてみました。また巨人が歩く衝撃に合わせてカメラを揺らします。

Starter Assets

今回は、無料の「Starter Assets – First Person Character Controller | URP」を使いました。

https://assetstore.unity.com/packages/essentials/starter-assets-first-person-character-controller-urp-196525

Playgroundシーンでは、プレイヤーにカメラのルートを表す空のゲームオブジェクトがあります。一人称視点用のバーチャルカメラはこのゲームオブジェクトを親にせず、インスペクタでFollowに設定しています。

バーチャルカメラのBodyプロパティは「3rd Person Follow」で、減衰や位置、距離などの値が0です。

TPSでも同じBodyプロパティが使われています。フィールドの値を0にすると一人称カメラに変わります。

TPS
FPS

また、Noiseプロパティでパーリンノイズが選択されていて、画面が常に揺れています。

Free Look Camera

ヒエラルキービューでCinemachine > FreeLook Cameraを追加します。

FreeLook Cameraは、マウス等の入力によってカメラがターゲットの周囲の軌道を回ります。デフォルトでは横方向に動かすとカメラがターゲットの周囲を周り、縦方向ではカメラの高さが変わります。

キャラクターの頭のゲームオブジェクトをFreeLook CameraのFollowとLookAtにアタッチします。

これで、FreeLook Cameraがキャラクターの周囲の軌道を周りながら、キャラクターの方を向き続けます。

軌道は3つのリグで指定します。これらはシーンビューでターゲットを囲う赤い円で表示されます。

インスペクアで各リグの高さや半径を変更できます。

リグごとに別のLookAtターゲットをオーバーライドできます。一番下のリグではバーチャルカメラが足元を向くようにしました。

Save During Playをオンにすると、プレイモードでの変更が保存されます。

バーチャルカメラを切り替える

Cinemachine Brainは、Priorityの値によってライブにするバーチャルカメラを選択します。フリールックカメラもバーチャルカメラと同様に扱われます。

バーチャルカメラを切り替えるには、スクリプトでPriorityの値を変更したり、残りのバーチャルカメラを無効化します。

スクリプト

using UnityEngine;
using Cinemachine;

public class TestVCameraSwitcher : MonoBehaviour
{
    [SerializeField] CinemachineVirtualCameraBase FPSCamera;
    [SerializeField] CinemachineVirtualCameraBase FreelookCamera;

    //bool freelook;

    private void Start()
    {
        FPSCamera.gameObject.SetActive(true);
        FreelookCamera.gameObject.SetActive(false);

        // FreelookCamera.Priority = 9;
        //FPSCamera.Priority = 10;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {

            FreelookCamera.gameObject.SetActive(FPSCamera.gameObject.activeSelf);
            FPSCamera.gameObject.SetActive(!FreelookCamera.gameObject.activeSelf);

            /*     
            freelook = !freelook;

            if (freelook)
            {
                FreelookCamera.Priority = 11;
                FPSCamera.Priority = 10;
            }
            else
            {
                FreelookCamera.Priority = 9;
                FPSCamera.Priority = 10;
            }
            */
        }
    }
}

バーチャルカメラやフリールックカメラの基底クラスのCinemachineVirtualCameraBaseクラスのフィールドを定義しているので、どちらのカメラもアタッチできます。

using UnityEngine;
using Cinemachine;

public class TestVCameraSwitcher : MonoBehaviour
{
    [SerializeField] CinemachineVirtualCameraBase FPSCamera;
    [SerializeField] CinemachineVirtualCameraBase FreelookCamera;

    //bool freelook;

片方だけをアクティブにしたり、Priorityを変更することで切り替えられます。

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {

            FreelookCamera.gameObject.SetActive(FPSCamera.gameObject.activeSelf);
            FPSCamera.gameObject.SetActive(!FreelookCamera.gameObject.activeSelf);

            /*     
            freelook = !freelook;

            if (freelook)
            {
                FreelookCamera.Priority = 11;
                FPSCamera.Priority = 10;
            }
            else
            {
                FreelookCamera.Priority = 9;
                FPSCamera.Priority = 10;
            }
            */
        }
    }

バーチャルカメラ間のブレンド

切り替える際バーチャルカメラ間をなめらかにブレンドできます。CinemachineBrainコンポーネントで、ブレンドのスタイルや時間を設定します。

Custom Blendsのリストで、特定のバーチャルカメラ間のブレンドを設定できます。

リストで定義されていないものは、Default Blendが使われます。

インパルスソース

巨人が足を踏み鳴らしたときにバーチャルカメラを揺らします。巨人の足のゲームオブジェクトにCinemachine Impulse Sourceコンポーネントを付けます。

Impulse Typeを「Propagating」にすると、遠くのインパルスが弱く遅くなります。Impulse Shapeで、インパルスの形状と持続時間を指定できます。

インパルスの生成

CinemachineImpulseSource.GenerateImpulseメソッドでインパルスを生成します。

using UnityEngine;
using Cinemachine;


[RequireComponent(typeof(CinemachineImpulseSource))]
[RequireComponent(typeof(AudioSource))]
public class GiantFoot : MonoBehaviour
{
    [SerializeField] FootstepSmokeVFXController vfxController;
    AudioSource audioSource;
    CinemachineImpulseSource impulseSource;

    private void Start()
    {
        audioSource = GetComponent<AudioSource>();
        impulseSource = GetComponent<CinemachineImpulseSource>();
    }
    public void Stomp()
    {
        // 足音を再生
        audioSource.Play();
        // インパルスを生成
        impulseSource.GenerateImpulse();
        // エフェクトを再生
        vfxController.PlayVFX(transform.position);
    }
}

GenerateImpulseAtメソッドの場合、引数に位置と速度を渡せます。足の着地する位置を渡してCinemachineImpulseSourceコンポーネントを一つにできます。

    
    // ...
    [SerializeField] CinemachineImpulseSource impulseSource;

    // ...

    public void Stomp()
    {
        // ...

        impulseSource.GenerateImpulseAt(transform.position, -Vector3.up);

        // ...
    }
}

巨人の歩くアニメーションのインポート設定でイベントを設定して、巨人のスクリプトを実行しています。

using UnityEngine;
using UnityEngine.AI;

public class TestGiant1 : MonoBehaviour
{
    // ...

    [SerializeField] GiantFoot leftFoot;
    [SerializeField] GiantFoot rightFoot;

    // ...


    void LeftFootStomp()
    {
        leftFoot.Stomp();
    }

    void RightFootStomp()
    {
        rightFoot.Stomp();
    }
}

インパルスに反応する

バーチャルカメラにImpulse Listenerコンポーネントをつけると、インパルスでカメラを揺らせます。

バーチャルカメラのAdd Extensionのドロップダウンメニューから「CinemachineImpulseListener」を選択してコンポーネントを追加します。

Gainでインパルス信号を増幅できます。Secondary Noiseを設定すると、インパルスに反応してカメラが揺れ続けます。

6D Shake
(none)

バーチャルカメラごとに設定を変えました。

実行

コメントを残す

メールアドレスが公開されることはありません。