Cinemachineでマウスホイールによるズームイン/ズームアウトを実現する方法を教えてほしいの…
スクリプトを書くことになるけど実現可能だわ。拡張機能(Extension)として作れば色々なカメラに適用できるようになっておススメだわ。
Cinemachineカメラをマウスホイールでズームイン/ズームアウトする方法の紹介です。
本記事では拡張機能(Extension)を用いて、既存のカメラワークにFOV制御を加える方法を紹介します。
拡張機能を用いると、任意のバーチャルカメラに対して挙動を拡張できるようになるため、柔軟性や汎用性が高まるというメリットがあります。
本記事の内容を実践すると、次のようなカメラワークが実現できます。
FOVの滑らかな変化を実現する方法も紹介します。また、Input Systemに対応させる方法も紹介します。
本記事で解説する方法は、マウスホイール操作を基本としていますが、キーボード入力やゲームパッドのジョイスティック入力などにも対応しています。
この作品はユニティちゃんライセンス条項の元に提供されています
- Unity2021.2.3f1
- Cinemachine2.8.2
- Input System1.1.1
目次 非表示
前提条件
予めCinemachineでキャラクターを追従するカメラワークがセットアップされているものとします。
セットアップ方法が分からない方は、以下記事をご覧ください。
拡張機能(Extension)とは
Cinemachineのバーチャルカメラの動作を拡張するためのコンポーネントです。バーチャルカメラは、複数の拡張機能を追加できる仕組みを備えています。
参考:Extension | Cinemachine | 2.6.0
今回は、マウスホイールでカメラのFOVを変える拡張機能を実装する形でズームイン/ズームアウト操作を実現していきます。
拡張機能について詳しく知りたい方は、以下記事も参考にしてください。
マウスホイールでズーム操作する拡張機能
初めに、マウスホイールでFOV調整する最小限の拡張機能の例です。マウスホイールの移動量取得にはInput Managerを経由しています。
スクリプトの適用方法
上記スクリプトをCinemachineUserInputZoom.csとしてUnityプロジェクト内に保存します。
保存したら、該当するバーチャルカメラのExtensions > Add Extensionから該当の拡張機能CinemachineUserInputZoomを選択します。
必要に応じてパラメータを調整します。
Input Nameにはマウスホイール入力の名前、Input Scaleには入力値に掛ける係数、Min FOVとMax FOVにそれぞれFOVの最小と最大を指定します。
実行結果
マウスホイールで段階的にズームイン/ズームアウトできるようになりました。
スクリプトの解説
スクリプトの内容について知りたい方向けに、要点を解説します。
独自の拡張機能クラスの定義
CinemachineExtensionの継承クラスを実装すると、拡張機能を自作することができます。
ユーザー入力の要求
次のコードで、Cinemachine側にユーザー入力を必要とするフラグを返すようにしています。
参考:Class CinemachineExtension| Cinemachine | 2.8.9
マウスホイールのスクロール量の計算
スクロール量の計算は、Updateイベントで行うようにしています。
Updateイベント内で行う理由は、後述するカメラ制御コールバックがFixedUpdateイベントから発行される可能性があり、この場合は正しくスクロールを検知できないタイミングが発生してしまうためです。
カメラ制御コールバックの定義
CinemachineExtension継承クラスでは、次のメソッド定義を必須としています。
引数の説明は割愛します。詳しく知りたい方は、以下公式リファレンスか記事をご覧ください。
参考:Class CinemachineExtension| Cinemachine | 2.8.9
ズーム処理は、Aimの処理が終わった後に行うようにしています。
FOVの補正量の計算
ズーム制御の肝となる部分は次のコードです。
マウスホイールがスクロールされていれば、_scrollDelta変数にスクロール量が積算されるので、カメラFOVの補正値_adjustFOVに加算しています。
FOVの下限と上限を設けているため、この範囲を超えないようにClamp関数で値を丸めています。
_scrollDeltaの値はUpdateイベント内で積算されるようになっているので、計算に使ったら0にリセットする必要があります。
FOVの反映
計算したFOVの補正値は、次のコードで加算して反映します。
補足コメントの通り、コールバック毎に毎回FOVを補正する必要があることに注意します。
滑らかなズーム操作に対応する
先述のサンプルに対し、滑らかにFOVを変化させるように改変した拡張機能スクリプトです。
以下の赤枠部分のパラメータが追加されています。
Smooth TImeにはFOVの変化にかかるおおよその時間、Max SpeedにはFOV変化の最大速度を指定します。
実行結果
FOVが滑らかに変化するようになりました。
動画では、おおよそ0.1秒かけてFOVを変化させるようにしています。
ソースコードの説明
主な変更箇所は以下部分です。
Mathf.SmoothDamp()メソッドを使ってFOVを目標値_targetAdjustFOVに滑らかに変化させるようにしています。
メソッドの戻り値を代入している_currentAdjustFOVに滑らかに変化するFOVが格納されます。
あとは、この値を補正値として加算するのみです。
SmoothDamp関数の使い方については、以下記事をご覧ください。
Input Systemへの対応
ここまで紹介した例では、すべてInput Manager経由でFOVを制御していました。
CinemachineがInput System経由で入力値を受け取れるようにするためには、CinemachineInputProviderコンポーネントをバーチャルカメラにアタッチしておく必要があります。
そして、拡張機能のスクリプト側では、このCinemachineInputProviderコンポーネントからInput Systemの入力値を参照するようにします。
参考:代替の入力システム | Cinemachine | 2.6.0
以上を踏まえたInput System対応版のサンプルスクリプトは次のようになります。
Input Systemシステムを使うためには、以下動画のようにCinemachineInputProviderコンポーネントを追加して、Z Axis項目にアクションを指定します。
実行結果は2つ目の例と一緒のため割愛します。
ソースコードの説明
Input System経由でスクロール量を取得する処理は次の部分です。
CinemachineExtension継承クラスでAwake()メソッドを定義する場合は、オーバーライドして必ずスーパークラスのAwake()メソッドを呼び出す必要があります。
参考:Class CinemachineExtension| Cinemachine | 2.8.9
そして、GetComponent()メソッドでCinemachineInputProviderコンポーネントを取得し、取得出来たらInput Actionのperformedイベントにスクロール量を取得する処理を登録します。
取得する軸はZAxisとしました。
また、このままではInput Managerを必ず参照してしまうため、Updateイベント内で次のようにCinemachineInputProviderを取得出来ていたら参照しないように対策しています。
さいごに
Cinemachineの拡張機能(Extension)を使うと、様々なバーチャルカメラに対して動きを加えることができるようになります。
また、Input Systemを使いたい場合はCinemachineInputProviderコンポーネントを通じて行うようにすると汎用性が高まるでしょう。
Input ManagerやInput System経由で入力値を取得する方式をとっているため、ゲームパッドなどあらゆる操作に対応しています。