Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
プレイヤーの画面とは別視点のリプレイを録画する
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// UnityEngineと名前空間を分ける
using ocv = OpenCVForUnity;
// 録画に使いたいカメラにつけるコンポーネント
[RequireComponent(typeof(Camera))]
public class OffscreenCaptureManager : MonoBehaviour
{
// 録画用のカメラが描画するテクスチャ
private RenderTexture _renderTexture;
// iOS端末以外で録画する際にRenderTextureから取得した画像を一旦Texture2Dに変換する
#if !(UNITY_IOS && !UNITY_EDITOR)
private Texture2D _convertTexture;
#endif
// 録画用のカメラの描画情報をOpenCV用のインスタンスに変更する
private ocv.Mat _mat;
// カメラから取得した描画情報を動画ファイルにするインスタンス
private ocv.VideoWriter _writer;
// 最後に録画した動画のファイルパス
private string _lastCapturedPath;
// 録画した動画を再生するプレイヤー
private UnityEngine.Video.VideoPlayer _player;
// 録画する動画の解像度。パフォーマンスにあわせて調整すると良い
private int _width = Screen.width;
private int _height = Screen.height;
// 初期化処理
void Start()
{
// 録画用のカメラにRenderTextureを設定する
_renderTexture = new RenderTexture(_width, _height, 24);
GetComponent<Camera>().targetTexture = _renderTexture;
// iOS端末以外ではRenderTexture → Texture2D → OpenCVForUnity.Matという順番で
// 変換する必要があるのでそれに使うインスタンスを生成
#if !(UNITY_IOS && !UNITY_EDITOR)
_convertTexture = new Texture2D(_width, _height, TextureFormat.ARGB32, false);
#endif
_mat = new ocv.Mat(new ocv.Size(_width, _height), ocv.CvType.CV_8UC4);
// プレイヤーを生成
_player = Camera.main.gameObject.AddComponent<UnityEngine.Video.VideoPlayer>();
_player.playOnAwake = false;
_player.renderMode = UnityEngine.Video.VideoRenderMode.CameraNearPlane;
_player.enabled = false;
}
void OnDisable()
{
EndCapture();
}
// 録画を開始する関数
void StartCapture()
{
// 撮影中の場合、一旦撮影を停止する
EndCapture();
// ファイルパスを生成。動作環境にあわせて拡張子を変えると吉
var fileName = Application.temporaryCachePath + "/" + System.DateTime.Now.ToString("yyyyMMddHHmmss") + ".mov";
// 動画生成インスタンスを初期化
_writer = new ocv.VideoWriter(
fileName,
ocv.VideoWriter.fourcc('M', 'P', '4', 'V'), // 動作環境にあわせてコーデックを変えると吉
30,
new ocv.Size(_width, _height),
true
);
// 録画した動画を後で再生できるようにファイルパスを保持
_lastCapturedPath = fileName;
}
// 録画を終了する
void EndCapture()
{
if (_writer != null)
{
// 録画を停止する(動画ファイルが作成される)
_writer.release();
_writer = null;
}
}
// 録画用のカメラの描画が終了したら動画ファイルに書き込む
void OnPostRender()
{
if (_writer == null)
{
return;
}
#if UNITY_IOS && !UNITY_EDITOR
// 描画情報をOpenCV用のインスタンスに流し込む
ocv.Utils.textureToMat(_renderTexture, _mat);
// 色情報を調整する
ocv.Imgproc.cvtColor(_mat, _mat, ocv.Imgproc.COLOR_BGR2BGRA);
// 動画ファイルに書き込み
_writer.write(_mat);
#else
// 描画情報を一度Texture2D型に流し込む
// 内部でTexture2D.ReadPixelsを呼んでいるので処理時間がかかります
ocv.Utils.textureToTexture2D(_renderTexture, _convertTexture);
// Texture2DをOpenCV用のインスタンスに流し込み
ocv.Utils.texture2DToMat(_convertTexture, _mat);
// 色情報を調整する
ocv.Imgproc.cvtColor(_mat, _mat, ocv.Imgproc.COLOR_RGB2BGR);
// 動画ファイルに書き込み
_writer.write(_mat);
#endif
}
// 最後に撮影した動画を再生する
void PlayVideo()
{
if (string.IsNullOrEmpty(_lastCapturedPath))
{
return;
}
_player.url = _lastCapturedPath;
_player.enabled = true;
_player.Play();
}
// 動画の再生を停止する
void StopVideo()
{
_player.Stop();
_player.enabled = false;
}
void OnGUI()
{
if (GUI.Button(new Rect(0, 0, 100, 100), "fps:" + ((int)(1f / Time.deltaTime)).ToString()))
{
}
if (GUI.Button(new Rect(0, 100, 100, 100), _writer == null ? "録画" : "終了"))
{
if (_writer == null)
{
StartCapture();
}
else
{
EndCapture();
}
}
if (GUI.Button(new Rect(0, 200, 100, 100), _player.enabled ? "停止" : "再生"))
{
if (_player.enabled)
{
StopVideo();
}
else
{
PlayVideo();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment