Unity + iOSでApplication.CaptureScreenshotを使わずにスクリーンキャプチャーをカメラロールに保存する

Unityを使っている時にスクリーンキャプチャを取ることが稀に良くあります。その時、いつも使っているのはApplication.CaptureScreenshot()メソッドでしたが、これをiOSで使うとDocuments内に保存されてしまい、カメラロールには保存されません。カメラロールに保存するためには、Documentsに保存した画像のパスを取得し、一度UIImageやNSDataを作成したあと、カメラロールに保存することができます。

しかし、この方法だと、Documentsに保存するまで待たねばならず、保存が完了したコールバックもないので、ファイルの存在を確認するループ処理書く必要があります。そして、保存するときにファイル名をユニークにしなければ、連続で撮影したいときに保存の確認がとれず、しばしば前回撮影した画像を保存してしまうことがありました。また、一時保存としてDocumentsを使用しているため、カメラロールに書き込みが終わったら画像を削除しなければなりません。

 

これらのことがあり、もっとちゃんと保存できるようにいろいろ試行錯誤した結果、Unity側で画面をTextureで取得し、byteデータにしてネイティブ側に渡すことで、一時保存させずにカメラロールに画像を保存することができました。ちなみに環境はUnity4.6.7f1、Xcode6.4です。

 

Unity

Unity側では画面をTextureで取得し、byteデータに変換したあと、ネイティブに渡しています。また、ネイティブから書き込み完了のコールバックを受け取るとインディケーターを停止するようにしています。

 

iOS

iOS側では、送られてきたbyteデータを、まずNSDateに変換し、NSDataをUIImageへ変換しています。変換したUIImageはUIImageWriteToSavedPhotosAlbumを使用し、カメラロールに保存しています。CaptureCallbackは、UIImageWriteToSavedPhotosAlbumの第三引数でコールバックを受け取るためにだけに使用しています。本来ならエラーログを出すべきですが、今回はそこまで重要ではないので省いています。また、これらのファイルはPlugins/iOSに配置し、ビルドした時に同時に吐出されるようにしています。

 

 

 

おわりに

今回作成したプログラムで今までずっとモヤモヤしていたものが解消されました。byteデータをやりとりするので、動作速度がどうなるか不安でしたが、結果的には全くストレスなく動作しました。むしろ今までのプログラムのほうが、書き込み待ちをしている分若干遅かったように思います。以前作ったアプリを次のイベントに向けてアップデートしようとしていた時にこの改修ができたので良かったです。

 

 

 

 

では、また。

 

●この記事を書いた人