プレイヤーの見ている画面とは別視点からのリプレイ動画をお手軽に作れないか頑張った話【Unity Advent Calendar 2017】

この記事はUnity Advent Calendar 2017 2日目の記事です。

ゲームを作っていると、ハイライトやリプレイをリザルトで出したいなーと思うことが常々あるかと思います。
最近だとPS4Nintendo Switchでプレーの録画をSNSにアップロードできたりしますよね。

UnityだとEveryplay SDKで録画機能を実装できます。

ただ、上記の録画機能はプレイヤーの見ている画面を録画していますが、
プレイヤーの見ている画面とは別視点からのリプレイ動画を作れないかな
と思い、今回いろいろ試してみました。

イメージはこんな感じ(ちょっと違うかな?)
f:id:takashicompany:20171202171555g:plain

作り方

簡単に言うと

  • ① カメラを2台用意する
    • プレイヤーの見る画面を描画するカメラ
    • リプレイの録画に使うカメラ
  • ② 録画用のカメラにRenderTextureを設定する
  • ③ RenderTextureの描画結果を動画ファイルに書き込む

という感じです。

(プレイヤー画面用のカメラと録画用のカメラの図)
f:id:takashicompany:20171202171823p:plainf:id:takashicompany:20171202171832p:plain

①と②はUnityですぐにできますが、③が考えどころです。
今回はOpenCV for UnityのVideoWriterという機能を使って動画ファイルを生成したいと思います。
f:id:takashicompany:20171202172013p:plain

実装

プレイヤーの画面とは別視点のリプレイを録画する


プレイヤーの画面とは別視点のリプレイを録画する


実際に録画された動画

実装の細かい話

  • Unity Editor(Mac)と、iOSで動作を確認
  • 上述した③ RenderTextureの描画結果を動画ファイルに書き込むOpenCVForUnity.Utils.textureToMat(Texture texture, Mat mat)OpenCVForUnity.VideoWriter.write(Mat image)で実現した
    • OpenCVForUnity.Utils.textureToMatで録画カメラのRenderTextureMatに変換。
    • ただ、textureToMat(Texture texture, Mat mat)iOSでしか動作しない(([作者も確認済みとのこと] (https://forum.unity.com/threads/released-opencv-for-unity.277080/page-28#post-3261290)))ので、他の環境ではRenderTextureを一旦Texture2Dに変換した上でMatに変換している
    • RenderTextureTexture2Dに変換する場合は内部でTexture2D.ReadPixelsを呼んでいるので処理に時間を要する
  • OpenCVForUnity.VideoWriter.writeで動画ファイルに書き込み
  • Androidも動画の拡張子とfourccの選択次第では動きそう(拡張子を.avi、fourccを`'M', 'J', 'P', 'G' (Motion JPEG)にしたら録画はできた。しかしVideoPlayerが再生に対応していなかったので今回のサンプルコードから外した)
  • iPhone SEで↑の動画と同じアプリを動かしたが処理落ちはそこまでなかった。解像度によっては処理落ちを招くケースがありそうなので、その辺は要調整
    • VideoWriter.writeを呼んでいるところは別スレッドに逃してもいいかも
    • iPad mini(4th gen)だと30FPSが15FPSまで下がった。おそらくだがRenderTextureの解像度を下げれば改善すると思う
  • OpenCVのモバイル用のプラグインが結構なサイズ(.frameworkとかだと500MB超えてたり)なので、ビルド時に不要な機能を消したりする必要はありそう

おわりに

今回はOpenCVForUnity(OpenCV)を使って動画の生成を実装しました。
改善すべきポイントは諸々ありますが、手早く作れるのが良いかなと。
ゲーム側でリプレイ機能を自前で作るとなると、設計時点でしっかりやる必要がありますしね😃
やはり理想を言うならネイティブプラグインでしっかり作るのがベストですね。