UnityでDebug.Logの内容をファイルに出力する
タイトルの内容に苦しんだらしき形跡を見かけたので「ググル・コピペ・ジツを使うのだ!」などと思っていたのですが、いざけんさくしたら案外出てこなかったので作りました。
LogWriter.cs
Unity標準のDebug.Log
クラスから出力されるログをコンストラクタのパスに指定されたファイルにひたすら追記していくクラスです。UniTaskに依存しています。[1]
使い方
こんな感じで使います。
private void Start()
{
// /Assets/StreamingAssets/log/example.txt
var path = Path.Combine(Application.streamingAssetsPath, "log", "example.txt");
var logWriter = new LogWriter(path, this.GetCancellationTokenOnDestroy());
}
private void Update()
{
Debug.Log(UnityEngine.Random.onUnitSphere);
Debug.LogWarning(UnityEngine.Random.ColorHSV());
Debug.LogError(UnityEngine.Random.rotation);
}
これを動かすとこんな感じに出力されます。
20210825022416 [L] (0.4, -0.8, -0.4)
20210825022416 [W] RGBA(0.545, 0.403, 0.468, 1.000)
20210825022416 [E] (0.4, 0.5, 0.5, 0.6)
20210825022416 [L] (-0.2, 0.9, -0.4)
20210825022416 [W] RGBA(0.078, 0.413, 0.256, 1.000)
20210825022416 [E] (0.0, -0.2, 0.7, 0.6)
20210825022417 [L] (0.6, 0.7, 0.3)
20210825022417 [W] RGBA(0.914, 0.453, 0.567, 1.000)
20210825022417 [E] (0.9, 0.0, 0.0, 0.3)
20210825022417 [L] (-0.1, -0.1, -1.0)
20210825022417 [W] RGBA(0.639, 0.688, 0.682, 1.000)
20210825022417 [E] (0.6, 0.3, 0.4, 0.7)
20210825022417 [L] (0.3, 0.0, 1.0)
20210825022417 [W] RGBA(0.274, 0.541, 0.482, 1.000)
20210825022417 [E] (0.0, -0.6, 0.2, 0.8)
コンストラクタに渡したCancellationToken
のキャンセルに反応してログの出力をやめますが、大抵の場合はアプリの起動から終了までログを残したいと思うので、DontDestroyOnLoad
したGameObject
からthis.GetCancellationTokenOnDestroy()
で作ったtokenを渡してあげればいいと思います。
実装のポイント
Application.logMessageReceivedThreaded
を使う
Debug.Log
のコールバックはApplication.logMessageReceived
とApplication.logMessageReceivedThreaded
がありますが、Threaded
がついていない方はメインスレッドからのログしか教えてくれません。わざわざファイルに書き出すからには、スレッド関係なしにログが欲しいだろうので、Threaded
の方を使いましょう。
スレッドセーフなQueueに格納する
Application.logMessageReceivedThreaded
はメインスレッド外からも飛んでくるのでスレッドセーフを考慮する必要があります。マルチスレッド処理は既存のクラスを使うに限るので、素直にBlockingCollection
に突っ込んで、別のところでループを回して中身を取り出してファイルに書き込みましょう。
本当ならBlockingCollection.GetConsumingEnumerable
を使いたいところですが、なぜか必ずforeach
の中でメインスレッドを停止させるのでTake
にしました。
スマートフォンでのログの取り出し方メモ
Android
-
AndroidStudio
のDeviceFileExplorer
とかadb
で取り出す
- X-ploreの見えるところに出力して端末をサーバにしてダウンロードする[2]
iOS
この処理をした上でApplication.persistentDataPath
にファイルを書き出す。
UnityEngine.iOS.Device.SetNoBackupFlag
にもパスを渡しておかないとiCloud
にバックアップされて面倒なことになるので注意。ログファイルの親ディレクトリを指定するべし。
まとめ
なんか毎回作っている気がするので、メモも兼ねて記事にしました。OnLogMessageReceivedThreaded
でログのフォーマットを作っているので、分析のためにcsv
にしたい場合などは適当にいじってください。
しかし調べても同じことをしている人の記事が出てこない。ほんとに? ほんとにないのか?
おしまい。
Discussion