(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!

    

Unity Recorderを使ってエディタを再生した時に自動で録画を行う【Unity】【アセット】【エディタ拡張】


このエントリーをはてなブックマークに追加



この記事でのバージョン
Unity 2018.4.13f1
UnityRecorder 2.0.3


はじめに

以前、Unity Recorderというエディタでプレイ中のゲーム内容を記録し、

動画やGIFなどの様々な形式で保存が出来るアセットを紹介しました。

Unity Recorder - Asset Store


このアセットは録画開始時にボタンを押す必要があるのですが、

Unityエディタを再生すると同時に録画も開始してくれたら便利かと思い、そんな拡張を作ってみました!

ついでに保存されたファイルが一定数を越えたら古い順に削除する拡張も作りました。


イメージとしては以下のような感じ。

f:id:kan_kikuchi:20200122053930g:plain


これがあれば「バグが発生したけど、どんな状況で起こったか確認したい」

みたいな時に動画で確認する事が出来てデバッグが捗ります!


なお、記事中では以下のアセットを使っています。

Villager Boy NPC V 2.6 | 3D Characters | Unity Asset Store



AutoRecorder

さっそくですがエディタが再生された時に自動で録画をするクラス、AutoRecorder

そのAutoRecorderの設定をするためのウィンドウ、AutoRecorderSettingsWindowのコードです。

なお、上記で紹介したUnity Recorderが導入済みの前提ですので、あしからず。



これらをEditorディレクトリに作成すると、

(AutoRecorderとAutoRecorderSettingsWindowは一つのファイルでOK)

f:id:kan_kikuchi:20200122044329j:plain


Tools/Auto Recorder/Settings Windowから設定用のウィンドウが開けるようになります。

f:id:kan_kikuchi:20200122044731j:plain


このウィンドウで「自動録画をするか」にチェックを入れれば準備完了。

なお、ファイル数の上限もこのウィンドウで設定可能です。

f:id:kan_kikuchi:20200122044741j:plain


後はUnity Recorderで録画したい形式を設定すれば、

f:id:kan_kikuchi:20200122044835j:plain


エディタを再生した時に自動で録画が開始され、

エディタの再生終了時に上限を超えたファイルの削除も行うようになります。

f:id:kan_kikuchi:20200122053930g:plain



実装解説

一応、実装方法について簡単に解説をしてみると、

まず再生開始や終了のイベントはEditorApplication.playModeStateChangedを使って取得しています。

//playModeStateChangedイベントにメソッド登録
EditorApplication.playModeStateChanged += OnChangedPlayMode;


次に自動録画の開始はRecorderWindowをのメソッドを使っています。

//Recorderのウィンドウ取得
var recorderWindow = (RecorderWindow)EditorWindow.GetWindow(typeof(RecorderWindow));
recorderWindow.StartRecording();


保存先のパスも同様にRecorderWindowから取得していますが、

設定ファイルの変数であるm_ControllerSettingsがprivateなので

リフレクションを使って無理やり取得しています。

//設定ファイル(private)を無理やり取得する
var windowType = recorderWindow.GetType();
var settingsFieldInfo = windowType.GetField("m_ControllerSettings", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance);
var recorderControllerSettings = (RecorderControllerSettings)settingsFieldInfo.GetValue(recorderWindow);


また、古い順からファイルを消す時にはタイムスタンプとLINQを使って判定をしています。

//対象ファイルのパスを取得
var filePaths = Directory
  .GetFiles (directoryPath, "*", SearchOption.AllDirectories) //ディレクトリ内の全ファイルを取得
  .Where(filePath => Path.GetFileName(filePath) != ".DS_Store")            //.DS_Storeは除く
  .OrderBy(filePath => File.GetLastWriteTime(filePath).Date)               //日付順に昇順でソート
  .ThenBy(filePath => File.GetLastWriteTime(filePath).TimeOfDay)           //同じ日付内で時刻順に昇順でソート
  .ToList();



さらに、AutoRecorderの設定の保存にはEditorUserSettingsを使っています。

EditorUserSettingsの値はAssetsディレクトリと同階層にある

Libraryディレクトリの中のEditorUserSettings.assetに保存されており、

普通Libraryディレクトリをバージョン管理に含まないので、個人ごとの設定が行えます。

/// <summary>
/// 自動録画をするか
/// </summary>
public static bool IsAutoRecord() {
  return !string.IsNullOrEmpty(EditorUserSettings.GetConfigValue(IS_AUTO_RECORD_SAVE_KEY));
}

//自動録画をするかのフラグを設定
private static void SetAutoRecordFlag(bool isAutoRecord) {
  EditorUserSettings.SetConfigValue(IS_AUTO_RECORD_SAVE_KEY, isAutoRecord ? IS_AUTO_RECORD_SAVE_KEY : "");
}