今回はUnityのゲームにゲーム画面のスクリーンショットを撮る機能を作成していきます。
ゲームユーザーが自身のブログやツイッターにゲームのスクリーンショットを載せたい時にあらかじめゲーム内でその機能が搭載されていると便利ですよね。
そんなわけでゲーム内にスクリーンショット機能を搭載し、ファイルに保存できるようにしていきます。
今回の機能を搭載すると
↑のような感じでボタンを押すとスクリーンショット画像が指定したフォルダに保存されるようになります。
今回はボタンを押すとスクリーンショットを撮るようにしていますが、キーボードを押した時や特定のタイミング(StartやUpdateメソッドで処理を記述して)で自由にスクリーンショットを撮ることが出来ます。
Unityのスクリーンショット機能
この後、ゲーム内にスクリーンショット機能を作成していきますが、スクリーンショットを撮る処理自体はすごく簡単です。
1 2 3 | ScreenCapture.CaptureScreenshot(ファイル名, 画面サイズ); |
ScreenCapture.CaptureScreenshotの引数にファイル名と画面のサイズを指定するだけです。
画面サイズは1が通常サイズで2にすると2倍、3にすると3倍の大きさとなります。
スクリーンショットのファイルはPNG形式で保存されるので、ファイル名の拡張子に.PNGを付けます。
スクリーンショット機能を試すだけならUnityEditor上で何らかのスクリプトのStartメソッドに
1 2 3 4 5 | void Start() { ScreenCapture.CaptureScreenshot(Application.dataPath + "/savedata.PNG"); } |
と記述すればAssetsフォルダ以下にsavedata.PNGファイルが保存されます。
Application.dataPathはゲームデータフォルダのパスを返すのでUnityEditor上ではAssetsフォルダ、スタンドアロン形式の場合はゲームのフォルダのパスを返します。
モバイル端末(iOS、Android)の場合はApplication.persistentDataPathで永続的な保存ディレクトリのパスを得られますのでこちらを使うといいと思います。
ゲーム内にスクリーンショット機能を搭載する
スクリーンショットを撮る処理がわかりましたので、サンプルを作成してみましょう。
スクリーンショット用UIの作成
まずはスクリーンショットで使うUIを作成していきます。
ヒエラルキー上にCanvasを作成し、名前をScreenShotとします。
その子要素にButtonを作成し、名前をScreenShotButtonとします。
ScreenShotButtonを押すとスクリーンショットの撮影をするようにします。
ScreenShotの子要素にPanelを作成し名前をLogPanel、その子要素にTextを作成し名前をLogTextとします。
LogPanelはスクリーンショットを撮った時に表示するテキストとして使います。
ScreenShotの子要素にCreate Emptyで空のゲームオブジェクトを作成し、名前をSuperSizePanelとします。
その子要素にSliderを作成し名前をSuperSizeSlider、Textを作成し名前をSuperSizeTextとします。
SuperSizePanelはスクリーンショット画像のサイズの指定と大きさの表示をします。
SuperSizeSliderのSliderのMin Valueに1、Max Valueに3を指定しWhole Numbersにチェックを入れ整数値で変化するようにします。
SuperSizeTextのTextには1を入れておきます。
UIの位置等は調整してください。
調整したUIは
↑のような感じにしました。
左上にScreenShotButton、SuperSizePanelを配置し、画面中央にLogPanelを配置しました。
これでUIが完成しました。
スクリーンショット機能のスクリプトの作成
UIが完成したので、ボタンを押した時に処理するスクリプトを作成していきます。
ScreenShotにScreenShotScriptスクリプトを新しく作成し取り付けます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using System.IO; using System; public class ScreenShotScript : MonoBehaviour { // スクリーンショットボタン [SerializeField] private GameObject screenShotButton; // ログパネル [SerializeField] private GameObject logPanel; // 解像度パネル [SerializeField] private GameObject superSizePanel; // 解像度レベルスライダー [SerializeField] private Slider superSizeSlider; // 解像度レベルテキスト [SerializeField] private Text superSizeText; // スクリーンショットを撮ってからの待ち時間 [SerializeField] private float waitTime = 5f; // データの保存先ファイルパス private string saveFilePath = "/Projects/ScreenShot"; // 保存ファイル名 private string saveFileName = "/screenshot.PNG"; void Start() { // UIの初期設定 screenShotButton.SetActive (true); logPanel.SetActive (false); superSizePanel.SetActive (true); // 指定したフォルダがない時はAssetsフォルダに保存 if (!Directory.Exists(Application.dataPath + saveFilePath)) { saveFilePath = ""; } } // スクリーンショットボタンを押す public void OnScreenShot() { StartCoroutine(OperationUI ()); } // スクリーンショット処理 IEnumerator OperationUI() { // スクリーンショットを撮る前にUIを全部非表示 screenShotButton.SetActive (false); logPanel.SetActive (false); superSizePanel.SetActive (false); // スクリーンショットを撮る ScreenCapture.CaptureScreenshot(Application.dataPath + saveFilePath + saveFileName, (int)superSizeSlider.value); // 待ち時間を入れないとlogPanelが表示されるので一定時間待つ yield return new WaitForSeconds (0.1f); logPanel.transform.GetChild (0).GetComponent<Text> ().text = "スクリーンショットを撮りました!\n" + Application.dataPath + saveFilePath + saveFileName + " に保存されました。"; // スクリーンショットを撮った旨を表示 logPanel.SetActive (true); yield return new WaitForSeconds (waitTime); // UIを元に戻す screenShotButton.SetActive (true); superSizePanel.SetActive (true); logPanel.SetActive (false); } // 画面サイズをテキストに表示 public void ChangeSuperSizeText(Single value) { superSizeText.text = value.ToString(); } } |
フィールドの前半部分では作成したUIのゲームオブジェクトをそれぞれ設定します。
ここで設定したUIはスクリーンショットを撮った時に画面内での表示と非表示の切り替えに使用します。
waitTimeはスクリーンショットを撮ってから次に撮るまでの待ち時間です。
saveFilePathは保存フォルダのパスで、Assetsフォルダ以下の階層の指定をします。
saveFileNameは保存ファイル名です。
StartメソッドではUIの初期の表示、非表示をしています。
その後、指定したフォルダが存在しなければsaveFilePathを空にし、Assetsフォルダの直下にファイルを保存できるようにします。
OnScreenShotメソッドはScreenShotButtonを押した時に呼び出すメソッドで、OperationUIをコルーチンを使って呼び出すだけです。
コルーチンに関しては
を参照してください。
OperationUIメソッドで実際のスクリーンショットを撮影する処理をしています。
ゲーム画面を保存する時に不要な要素(スクリーンショット関連のUI)等をまず非表示にします。
その後、
1 2 3 | ScreenCapture.CaptureScreenshot(Application.dataPath + saveFilePath + saveFileName, (int)superSizeSlider.value); |
でスクリーンショットを撮ります。
第1引数にファイルまでのパスを指定し、第2引数はファイルのサイズをSuperSizeSliderの値を指定しています。
スクリーンショットを撮った後すぐにUIを表示するとそのUIもスクリーンショットされてしまうので、
1 2 3 | yield return new WaitForSeconds (0.1f); |
で一定時間待った後その後の処理を実行します。
LogPanelの子要素のTextにはスクリーンショットしたファイルの保存先のパスを表示します。
LogPanelはwaitTime秒だけ表示し、その後は元の画面に戻しています。
ChangeSuperSizeTextメソッドはSuperSizeSlidierの値を変更した時に呼び出し、SuperSizeTextの値を書き換えます。
引数としてSingle型の引数を取るようにし、Dynamicな値を取得出来るようにしておきます。
これでスクリプトが完成しました。
UIからメソッドを呼び出す
スクリプトが完成したので、UIを操作した時にスクリプトのメソッドを呼び出すようにしていきます。
まずはScreenShotButtonのOnClickにScreenShotゲームオブジェクトに設定したScreenShotScriptを設定し、OnScreenShotメソッドを呼び出すようにします。
次にSuperSizeSliderのOnValueChangedにScreenShotScriptスクリプトのChangeSuperSizeTextメソッドを指定します。
この時に指定するメソッドはDynamicなChangeSuperSizeTextメソッドを指定するようにします。
これでUIの設定も終わりました。
サンプルを試すと記事の最初の動画のようになります。
動画内ではスクリーンショットの保存先のApplication.dataPathはカットして表示しています。
終わりに
ゲーム画面のスクリーンショットならキーボードのPrintScreenShotキーを押すだけでも良いかなと思ったんですが、不要な要素も映ってしまうので、ゲーム内でスクリーンショット機能があると便利ですね。
PS4とかXBoxOne向けのビルドをした場合はどうなるんでしょうね?(-_-)