『エア搬入T.T.』のPV撮影におけるCinemacineとUnity Recorderについて

GWの「エアコミケ」期間中にunityで『エア搬入TT』というレースゲーを作ったことを前回の記事でお話いたしました。
dnasoftwares.hatenablog.com
今週は「博麗神社例大祭」中止に伴う「エア例大祭」をやるぞー、ということで


大ボスからネタ(と資料)を振られてしまったので作っておりました。

紆余曲折七転八倒しましたが、当初の例大祭の設営搬入をやっているぐらいの時間帯に新バージョンを公開できました。
www.dna-softwares.com

……なぜかunityroomで起動しないバイナリになってしまったので、自分のサークルのサイト上での公開ですが。
今度naichiさんに聞かなきゃ……

Unity上でカッコイイ映像素材をつくる

ゲームが完成したらやはりPVを作りたいのです。というよりPV作らないと今のご時世、拡散されない可能性が高いです。
せっかくレースゲーなんで、理想は高くこんな感じで。

youtu.be

カメラワークの参考も兼ねて最近ずっとベストモータリング/ホットバージョンの動画ばっかり見てるんですよ、テレビ流し見感覚で見られるので良い。

幸いUnityには良い感じのカメラワークを作ってくれるパッケージと動画を撮るパッケージのそれぞれが公式で供給されています。それが表題のCinemacineとUnity Recorderです。

Cinemachine

unity.com
プロシージャルに特定の物体を追うカメラワークを作れる便利なパッケージですが、カメラをスイッチングさせるのはどうもTimelineあたりを使わせる前提のようです。
ClearShotを使えば「被写体が障害物で隠れたら別アングルにする」という処理は自動化できますが、イベント会場ってそんなに障害物があるわけじゃないので、一つのカメラに固定されがちになる可能性が高くあまり期待できません。
そこで、今回は自前でカメラをアクティベートするスイッチを作ります。

Unity Recorder

docs.unity3d.com
Gameビューを録画するだけでなく任意のレンダーテクスチャをキャプチャできるのが大きい。今回はこの機能に着目しました。

これら2点を組み合わせて、普通の通しプレイをCinemacineで追い、ゲームの裏でキャプチャするという仕組みをこさえることとしました。

プランニング

まずは録画に使うシーンを複製して新しいシーンをこさえます。色々付け足すので、ゲーム本体とは分離しましょう。

カメラを置く場所を固定しなければならないので、事前に走行ルートを決めてしまいます。ルートを決めたらチェックポイントやカーブの走行ラインを想定してVirtualCameraを配置。

f:id:dnasoftwares:20200517002248p:plain
緑線→想定ルート 白矢印→チェックポイント 赤丸数字→通過順 カメラと歯車のアイコン→CinemacineVirtualCameraの設置場所

あとはこれを車両が近づいたときアクティベートしていけば、それっぽいカメラワークができるはず、というわけです。

スイッチの準備

指定オブジェクトが特定の範囲に入る、はTriggerを使えば実現できそうです。こんなコードを用意しました。

using UnityEngine;

public class VCamActivationBoundary : MonoBehaviour
{
    [SerializeField] private Cinemachine.CinemachineVirtualCamera vCamTocativate; // この判定でON/OFFするVirtualCameraの参照
    [SerializeField] private bool activateOnlyOnce; // 一度きり?(falseだと何度出入りしてもスイッチングする。trueの場合は最初の一度だけ)

    private bool _activated; // 一度スイッチングした?

    private void Start()
    {
        vCamTocativate.enabled = false; // 初期状態はカメラOFFから
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.layer!=LayerNames.Vehicle && other.gameObject.layer!=LayerNames.VehicleBody ) return; // ゲーム固有処理。自車両のオブジェクト以外がトリガーに触れてもなにもしない
        if (activateOnlyOnce && _activated) return; // 一度きり反応の設定がONで既に一度スイッチングしてるならなにもしない
        vCamTocativate.enabled = true; // VirtualCamera有効
        _activated = true; // 一度スイッチングした
        Debug.Log(vCamTocativate.name+" Activated");
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.gameObject.layer!=LayerNames.Vehicle && other.gameObject.layer!=LayerNames.VehicleBody) return;
        vCamTocativate.enabled = false; // VirtualCamera無効
        Debug.Log(vCamTocativate.name+" Deactivated");

    }
}

これで、VirtualCameraがTriggerに入ったらON、出たらOFFの動作が実装できました。
実際の走行ルートを考えてカメラのスイッチング範囲を設定し、カメラをリンクさせていきます。いずれのカメラ範囲にも入っていない場合は自車両視点のカメラを適当に選んで貰うようにします。これにはClearShotが好適でしょう。
車両手前からルーズに捉えるビュー、車の真上から車両周辺を広く捉えるビュー、一人称視点を用意し、ランダムで選ばせます。プライオリティを最低にして常駐させておけば、他のカメラが全てOFFのときは自動的に車両追尾になるというわけです。
残りのVirtualCameraは適当にプライオリティを設定しますが、スイッチング範囲が重なったとき、基本的には古いカメラよりは新しいカメラの視点の方が優先されるべきだろうと思いますので、スイッチングの順番にVirtualCameraのプライオリティを上げていけば良いと思います。(最初のカメラ=最低、でそれから順番に1ずつ足す)

動作テストとキャプチャ

さて実装したらテストをしなければなりませんが、ゲームを遊びつつCinemacineの生成結果をプレビューする必要があるわけです。流石にCinemacineの画面だけ見てプレイするのはただのラジコン操作以上の難しさなので、ここではゲーム画面は元のまま残しつつ、Cinemacineの出力を小さくプレビューさせようと思います。
といってもやることは単純で

  • 出力したい動画の縦横と同じサイズのレンダーテクスチャアセットを新規作成
  • Cinemacineで制御する録画用カメラの出力先をレンダーテクスチャにする
  • そのレンダーテクスチャをUI Raw ImageでゲームUIと一緒に表示する

だけです。Unity Recorderではレンダーテクスチャをキャプチャ(録画)対象にできるので、これでUnity Recorderの準備も一緒にできたようなものです。
操作方法に従い適当に録画設定を作成。「Capture」を「Render Texture Asset」にして、先ほどのレンダーテクスチャを指定。あとはSTART RECORDINGを押してゲームを遊べば外部視点が勝手に録画されるという寸法です。
録画を始めずに単に実行すればテストになりますので、カメラワークや反応範囲を調整して、出来たと思ったら録画ONにして通しプレイ。事故や曲がるところの間違いに気をつけつつ走りきったらあとは適当な編集ツールで好きにしましょう。

実際にカメラが動いている様子をエディタビューごとキャプチャしてみました。スイッチング範囲も可視化されているのでカメラの切り替わりがわかりやすいかなと思います。

エア搬入T.T. PV(?)メイキング

まとめ

この方策、比較的元のゲームに手を付けずに実装できるのでとっかかりは楽です。ただ、如何せん毎回手操作が必要なので全く同じ動作が再現できないのが厳しいところ。
マジメにやるならリプレイシステムの実装も必要ですが、UnityでRigidbody絡んで可変FPSでリプレイとか地獄しか見えませんね……
ゲームのジャンルによりますが、簡易なPVであればこういった手法で素材映像を作るのも悪くないのではと思います。
ただ、Unity Recorderがちょっと重いらしく、音声を同時キャプチャすると高確率で動画とズレるのが大問題。PVで効果音がほとんど入ってないのはそこが理由です。(そもそもキャプチャの段階で音声を録音していない)
この辺はもうちょい正確な方法を探しています。

記事中ではエアコミケ用のコミケ会場を模した東京コースを使いましたが、同じ手法で静岡コースにカメラを配して作った新しいPVではさらに事後の編集も多めにしています。

【エア例大祭】エア搬入T.T. 静岡コースPV

  • ちょっと早回し(×1.1~×1.2)にして間延びを抑える
  • 長距離移動シーンはカッコイイ所だけ残す
  • スピード感あるシーンが欲しかったのでチェックポイントを一部無視
  • 普通のゲームプレイも録画して一部に混ぜる

最初のPVよりはまあまあメリハリある動画になったかなと思います。

というわけで課題はあるものの動画素材をそこそこ早く用意するにはいい手じゃないかと思っています。
3DゲームのPV作成で悩んだらCinemacine+UnityRecorderでコンピュータ任せのカメラワーク、それなりにお勧めです。