Unity でスクリーンショットを撮る
Unity でスクリーンショットを撮る Application.CaptureScreenshot
について調べてみたこと。
概要
Application.CaptureScreenshot
でスクリーンショットが撮れるfilename
にはパスを渡すことができる- 保存は非同期で行われる
- デフォルトは端末の画面サイズになる
環境
- Unity 5.3.1p3
- Android 6.0.1
基本的なこと
Application.CaptureScreenshot | Unity Scripting API に書いてあること。
- filename でスクリーンショットの保存ファイル名を指定する
- superSize で解像度を増やすことができる
- 縦横それぞれ n 倍になるので、画像の大きさは n^2 倍になる
- デフォルトは 0 (・・・だと!?)
- Web Player では使えない(なにも起こらない)
- モバイル端末では、persistent data path 以下に保存される
以下、モバイル端末(iOS/Android)を前提とする。
調べたこと
filename にはパスを渡すことができる
Application.CaptureScreenshot("images/screenshot.png");
スクリーンショットは <アプリのデータディレクトリ>/images/screenshot.png
に保存される。
このとき、images
ディレクトリが無いとスクリーンショットを保存できない。
なお、その場合 Exception が投げられることはなく、コンソールに Failed to store screen shot
というログが出るだけ。
System.IO
を使ってディレクトリを作っておく。
Directory.CreateDirectory(Path.Combine(Application.persistentDataPath, "images"));
Application.CaptureScreenshot("images/screenshot.png");
保存は非同期で行われる
保存には 1 フレーム以上の時間がかかる。何フレームかかるかは、端末の性能に依る。
IEnumerator CaptureScreenshot(string fileName)
{
Application.CaptureScreenshot(fileName);
// ここでは、まだ保存できていない
yield return null;
// ここなら、性能が良い端末なら保存できているかも
}
撮ったスクリーンショットを SNS に投稿したい場合などは、System.IO.File.Exists
でファイルが存在することを確認する必要があるだろう。
雑に書くと以下の様な感じ。
IEnumerator CaptureScreenshot(string fileName)
{
Application.CaptureScreenshot(fileName);
var filePath = Path.Combine(Application.persistentDataPath, fileName);
while (!File.Exists(fullPath))
{
yield return null;
}
// 保存できている
}
ちゃんと書くとしたら、少なくとも以下の点ぐらいはなんとかしておきたい。
Application.CaptureScreenshot
する前に、既に同名のファイルが存在する場合に対応する- 保存にタイムアウトを設ける(無限ループさせないようにする)
デフォルトは端末の画面サイズになる
superSize = 0
では、端末の画面サイズのスクリーンショットが撮られる。
1 以下の値を指定しても、同様の結果になる。
まとめ・感想
filename
にはパスを渡せば、persistentDataPath
内の好きなディレクトリに保存できる- 保存は非同期で行われるので、
System.IO.File.Exists
などで保存できたことをチェックする - デフォルトは端末の画面サイズになり、
superSize
に 1 以下の値を設定しても同様の結果になる
手軽にスクリーンショットを撮ることができるが、保存が非同期で行われるのにコールバックの仕組みが無いので、 撮ったスクリーンショットをどうこうしたい場合はちょっと面倒だと思う。 多分 Camera から texture が取得できると思う(要出典)ので、そちらを使うほうが良さそう。
一方で、自動テストの際に、画面見たまんまを撮影するのには便利そう。
追記
ちゃんと書くとしたら、少なくとも以下の点ぐらいはなんとかしておきたい。
Application.CaptureScreenshot
する前に、既に同名のファイルが存在する場合に対応する- 保存にタイムアウトを設ける(無限ループさせないようにする)
というのを Unity で独自のコルーチンを定義する | KAKELOG でやってみた。