Unityでインディゲームを作る!

Unityでのゲーム制作を目指し、それに関わる話題についてのブログ

Unity Cinemachineを使って、ダッシュ時に自動で進行方向に向くTPSカメラを作る!

CinemachineAdaptiveCamera_Cover

 今回はUnity公式のカメラ制御システムであるCinemachineを使って、マウスなどでカメラをコントロールしつつも、ダッシュ時には進行方向に自動で向いてくれるカメラを作ってみたいと思います。

 カメラの制御は特に3Dゲームで重要で、カメラ操作が多すぎるとプレイヤーへの大きな負担になってしまいます。ゲーム性にもよると思いますが、出来る限りカメラ操作をする量や場面を減らしたいものです。

 そこで今回は歩き時は俯瞰でプレイヤーの周りを見る視点で、走るとプレイヤーの進行方向が良く見えるようにカメラが自動で向いて寄る、というカメラ制御をCinemachineを使って再現してみたいと思います。Recentering機能を使えば、実はかなり簡単に再現することが出来ました。

 

 そして、今回の記事ではInput Systemを入力システムとして採用しています。また、今回の方式はあくまで実験的な内容なので、そのまま本番環境で使えるとは限らない点をご了承ください。

 

準備

 当然ですが、Cinemachine パッケージがインストールされている必要があります。今回は公式デモ・アセットであるStarter Assetsのロボのモデルを使って、Charactor Controllerを利用したプレイヤーキャラを用意しました。ただ移動(歩きとダッシュ)をするだけの簡素なモノです。Player Inputコンポーネントも同じオブジェクトに装着しています。

 そして、FreeLook Cameraヒエラルキー上に追加!メインカメラに自動的にCinemachine Brainコンポーネントが追加されます。FreeLook Cameraはプレイヤーがマウスなどで操作できるのですが、Input System利用時にはインスペクター上から Input Providerコンポーネントの追加が必要です。Followやカメラの距離などの設定を入力すれば準備完了。

 

カメラ視点の意図

 単純な視点操作できるTPS視点カメラだけならコレで完成になります。画面の中心に自キャラが位置し、プレイヤーがキャラとその周辺を見るのに最適な設定であり、ある程度の俯瞰性があるので頻繁にカメラを動かす必要もないし、プレイヤーの動きにカメラがいちいち追随することも無いです。(あくまでこれが今回のカメラ制御に求める挙動であり、適切なカメラ設定はゲーム性によります)

AdaptiveCamera_Walk mode

 問題は走った時で、走るとプレイヤーキャラ周辺ではなく、中距離あるいは長距離のある程度離れた方向に目を向けることが多いと想定すると、この場合プレイヤーは足元付近から前方へと自分でカメラを操作する必要が出てきます。

AdaptiveCamera_Dash mode

 この走り始めた時のカメラ操作を省きたい、というのが今回の意図です。走るということは目的地は少し離れているのであり、その少し離れた地点にカメラが自動で向けば楽だろう、便利だろうということです。

 

Recenteringを使えば簡単!

SwitchingAndRecentering

 というわけで、すこし前置きが長くなりましたが、C#スクリプト上にCinemachineFreeLookインスタンスを作り、そこから

CinemachineAdaptiveCamera_Inspector

m_RecenterToTargetHeading.m_enabledにアクセスすれば、意外と簡単に出来てしまいます。後述しますが、ここでダッシュ時の別のFreeLook Cameraの優先度を100にすることでカメラを切り替えています。

 

 Recenteringとはカメラを定位置(この場合、真後ろ)に自動で戻す機能で、X軸とY軸それぞれあり、インスペクター上でも実は簡単にON/OFF切り替えが出来たりします。ダッシュ時にはこれをtrueにし、立ち止まったり歩きに戻したらfalseにするようにします。

SwitchRecenteringOnDash

 

 ※ダッシュ切り替えをトグルにするべきか、あるいはボタンを押しっぱなしにするかのデザインについては諸説あると思いますが、今回はトグル方式でボタンを押すと交互に切り替わる、という方式にしています。

 

もう一台のFreeLook Cameraを使う

 自動で走る方を向くだけなら、実はもうこれだけでいいのですが、進行方向を向くと同時にプレイヤー側にカメラが寄って欲しいので、もう一台、ほぼ同じ設定の距離や高さを変えたカメラを用意してそれに切り替わるようにします。

 走るということはキャラ周辺には用が無く、遠くまで見渡せた方が良いと考えるからです。そのためにはプレイヤー側によって、少しでも前方への視野を拡げます。

 

 今回の場合、カメラ操作を残しつつダッシュ時にカメラ切り替えも考慮するとなると、工夫をしないとカメラがスムーズに切り替わりません。Cinemachineはアクティブなカメラの中で優先度が一番高いカメラに自動でトランジションしてくれますが、意図しないブレンドになる可能性がこの場合高いからです。

SyncInputToCamera

 なので、今回考えた作戦は片方のFreeLook Cameraへの視点移動入力をもう片方にも同時に入力しておく、というものです。FreeLook及び、Input Providerによるデータ入力はそのカメラがアクティブな時に限られます。なので、スタンバイ状態にあるFreeLookには手動で入力して、二つのカメラの位置をシンクロさせておく、という作戦です。

 Cinemachineにおけるカメラ切り替えはPriority(優先度)を変えたり、優先度の高いカメラをSetActiveで有効にするなどがありますが、スムーズなブレンディングのためにスタンバイ状態のカメラもプレイヤーに追随しておく必要があるので、今回は優先度のコントロールのみで切り替えます。

CinemachineAdaptiveCamera_UpdateMethod

 Updateメソッドの中でSyncFreeCamsメソッドを実行し、常に二つのカメラに同じ視点操作を入力します。そして、ダッシュ有効時にカメラの優先度を上げて、

m_RecenterToTargetHeading.m_enabledをtrueにしてカメラを切り替えます。

 ふたつのカメラは実際にはプレイヤーとの距離が違うので完全にシンクロすることはありません。しかし、スタンバイ状態でも常にカメラ操作とダッシュ時の自動制御に基づいて同じ方向に移動しているので、切り替え時にスムーズなカメラ・ブレンディングを実現することが出来る、ということになります。

 

まとめ

 というわけで、最初はコレできたらかなり便利だな、出来るかな?と不安でしたが、やってみると意外とすんなり素早く出来て、Cinemachineの素晴らしさを改めて認識しました。Timelineなどとの統合性を考えるとカメラ・システムはCinemachineを中心に考えていきたいので、これからも更にCinemachineへの理解を深めたいと思います。