search
LoginSignup
59

posted at

updated at

【Unity】UnityEditor上でスクリーンショットを撮る方法、UnityRecorderとスクリプト

概要

UnityEdito上でスクリーンショットを取る方法について説明します。
大きく分けてUnity Recorderを使う方法と、スクリーンショットを撮るスクリプトを書いて使う方法があります。
この記事ではスクリプトを使う場合のサンプルコードも掲載しています。

※2018年に執筆した時、備忘録程度に雑に描いた記事なのですが…思ったよりも使ってる人が多かったので2022年7月に大幅な記事のリライトを行いました。

【1-1】Unity Recorderの説明

UnityにはUnity RecorderというUnityが作ってる公式のアセットがあります。
こちらを使う事でUnityEditor上で再生されたGameタブをイメージ(JPEG,PNG,EXR)、ムービー(MP4,WebM,QuickTime)、アニメーションクリップ形式、GIF、オーディオ(WAV)、AOV(JPEG,PNG,EXR)で保存できます。

【1-2】Unity Recorderの導入

2022-07-01_13h36_47.png
1.UnityEditorのメニューから「Window」→「PackageManager」を選択して、PackageManagerを開きます。
2022-07-01_13h38_56.png
2.左上のタブを「Unity Registry」に変更した後、右上の検索欄に「Unity Recorder」と入力します。
2022-07-01_13h42_56.png
3.「Unity Recorder」の詳細が表示されてる状態で右下の「Install」を押すことで導入完了です。

【1-3】UnityRecorderの利用

2022-07-01_13h45_18.png
「Window」→「General」→「Recorder」→「RecorderWindow」を開くとRecorderの設定画面が開けます。
UnityRecorder_HOW.png
大まかな使い方の流れは…
1.「Add Recorder」から撮影したいメディアを追加。
2.設定Windowでメディアの設定を行う。
3.左上の再生ボタンを押すとUnityが実行されて撮影が始まる。

詳細なマニュアルについては下記リンクをご確認ください。
Recorder ウィンドウからのレコーディング

【2-1】スクリーンショットを撮るスクリプトを書く

ScreenShot.cs
using System;
using System.Collections;
using System.IO;
using UnityEngine;

namespace ScreenshotUtility
{
    //タイムスタンプの書式設定
    public enum TIME_STAMP
    {
        MMDDHHMMSS,
        YYYYMMDDHHMMSS,
    }

    //背景色の設定
    public enum BACK_GROUND_COLOR
    {
        Alpha, //透過PNG
        CustomColor, //カスタムカラー
        Skybox, //スカイボックス
    }

    //解像度の設定
    public enum SCREEN_SIZE_PIXEL
    {
        //1:1
        p256x256,
        p512x512,
        p1024x1024,
        p2048x2048,
        p4096x4096,

        //16:9
        p1280x720, //HD
        p1920x1080, //FullHD
        p2560x1440, //2k
        p3840x2160, //4k
        CustomSize //指定したピクセルサイズで出力(下限32/上限4096)
    }

    public class ScreenShot : MonoBehaviour
    {
//UnityEditorのみで実行
#if UNITY_EDITOR
        [Header("撮影に使うカメラの割り当て")]
        [Tooltip("撮影に使うカメラを割り当ててください"), SerializeField]
        Camera _UseCamera;

        [Header("画像のサイズの設定")]
        [Space(10)]
        [Tooltip("ScreenSizePixelをCustomにするとCustomSizeの解像度が適用されます"), SerializeField]
        SCREEN_SIZE_PIXEL _screenSizePixel = SCREEN_SIZE_PIXEL.p1024x1024;

        [Tooltip("ScreenSizePixelがCustomになってる場合の解像度設定(下限32Pixel/上限4096Pixel)"), SerializeField]
        Vector2Int _customSize = new Vector2Int(1024, 1024);

        [Header("背景色の設定")]
        [Space(10)]
        [Tooltip("Alpha:背景透過 White:白 CustomColor:指定した色 Skybox:スカイボックス"), SerializeField]
        BACK_GROUND_COLOR _buckGroundColorType = BACK_GROUND_COLOR.Alpha;

        [Tooltip("BuckGroundColorTypeがCustomの場合の背景色"), SerializeField]
        UnityEngine.Color _customColor = UnityEngine.Color.green;

        [Header("ファイル名の書式設定")]
        [Space(10)]
        [Tooltip("タイムスタンプの書式設定"), SerializeField]
        TIME_STAMP _timeStampStyle = TIME_STAMP.MMDDHHMMSS;
        [Tooltip("ファイル名の先頭に付く文字列"), SerializeField]
        string _screenShotsTitle = "img";

        [Header("保存先のフォルダ名")]
        [Space(10)]
        [Tooltip("スクリーンショットを保存するフォルダ名 Assetsフォルダーの直下に配置されます"), SerializeField]
        string _screenShotFolderName = "ScreenShots";

        [Header("実行中の撮影キー")]
        [Space(10)]
        [Tooltip("Unity実行中にスクリーンショットを撮る場合のキーバインド")]
        public KeyCode _screenShotsKeybinding = KeyCode.F1;

        [Header("Consoleに保存先のパスのログを出力します")]
        [Space(10)]
        [Tooltip("チェックをすると、画像のファイル名と画像の保存先のパスのログの出力します"), SerializeField]
        bool _consoleLogIsActive = true;

        void Update()
        {
            if(Input.GetKeyDown(_screenShotsKeybinding))
            {
                getScreenShots();
            }
        }

        private bool NullCheck()
        {
            bool isNull = false;
            if(_UseCamera == null)
            {
                Debug.LogWarning("画像の書き出しに使用するカメラを ScreenSchotCamera に割り当ててください");
                isNull = true;
            }
            if(_screenShotsTitle == "")
            {
                Debug.LogWarning("ScreenShotsTitle に画像ファイルに付ける末尾の文字を入力してください");
                isNull = true;                
            }
            if(_screenShotFolderName == "")
            {
                Debug.LogWarning("ScreenShotFolderName にScreenShotの保存先のフォルダ名を入力してください");
                isNull = true;                
            }            
            return isNull;
        }
        
        [ContextMenu("スクリーンショットを撮影する")]
        public void getScreenShots()
        {
            //NullCheck
            if(NullCheck()){ return; }
            // Application.dataPath = ../Assets
            string path = UnityEngine.Application.dataPath + "/" + _screenShotFolderName + "/";
            StartCoroutine(imageShooting(path, _screenShotsTitle));
        }

        //撮影処理
        //第一引数 ファイルパス / 第二引数 タイトル
        private IEnumerator imageShooting(string path, string title)
        {
            yield return new WaitForEndOfFrame();

            //パスの作成
            imagePathCheck(path);
            string name = title + getTimeStamp(_timeStampStyle) + ".png";

            //元々の背景色をCache
            Color32 CacheColor = _UseCamera.backgroundColor;
            //背景色:透過
            if(_buckGroundColorType == BACK_GROUND_COLOR.Alpha)
            {
                _UseCamera.backgroundColor = new Color32(0, 0, 0, 0);
                _UseCamera.GetComponent<Camera>().clearFlags = CameraClearFlags.SolidColor;
            }
            //背景色:カスタム
            if(_buckGroundColorType == BACK_GROUND_COLOR.CustomColor)
            {
                _UseCamera.backgroundColor = _customColor;
                _UseCamera.GetComponent<Camera>().clearFlags = CameraClearFlags.SolidColor;
            }
            //背景色:スカイボックス
            if(_buckGroundColorType == BACK_GROUND_COLOR.Skybox)
            {
                _UseCamera.GetComponent<Camera>().clearFlags = CameraClearFlags.Skybox;
            }

            //スクショ作成
            //書き出しサイズの取得
            Vector2Int size = getScreenSizePixel2Int(_screenSizePixel);
            Texture2D screenShot = new Texture2D(size.x, size.y, TextureFormat.ARGB32, false);
            RenderTexture rt = new RenderTexture(screenShot.width, screenShot.height, 32);
            RenderTexture prev = _UseCamera.targetTexture;
            _UseCamera.targetTexture = rt;
            _UseCamera.Render();
            _UseCamera.targetTexture = prev;
            RenderTexture.active = rt;
            screenShot.ReadPixels(new Rect(0, 0, screenShot.width, screenShot.height), 0, 0);
            screenShot.Apply();
            byte[] bytes = screenShot.EncodeToPNG();
            //UnityEngine.Object.Destroy(screenShot);

            //書き込み
            File.WriteAllBytes(path + name, bytes);

            //ログの表示
            if(_consoleLogIsActive)
            {
                Debug.Log("Title: " + name);
                Debug.Log("Directory: " + path);
            }

            //カメラの背景色を元に戻す
            _UseCamera.backgroundColor = CacheColor;
            //Assetフォルダのリロード
            UnityEditor.AssetDatabase.Refresh();
        }

        //ファイルパスの確認
        private void imagePathCheck(string path)
        {
            if (Directory.Exists(path))
            {
                //Debug.Log("The path exists");
            }
            else
            {
                //パスが存在しなければフォルダを作成
                Directory.CreateDirectory(path);
                Debug.Log("CreateFolder: " + path);
            }
        }

        private Vector2Int getScreenSizePixel2Int(SCREEN_SIZE_PIXEL ScreenSize)
        {
            //デフォルト設定
            Vector2Int size = new Vector2Int(1024, 1024);
            switch(ScreenSize)
            {
                //1:1(正方形)
                case SCREEN_SIZE_PIXEL.p256x256:
                    size = new Vector2Int(256, 256);
                    break;                
                case SCREEN_SIZE_PIXEL.p512x512:
                    size = new Vector2Int(512, 512);
                    break;
                case SCREEN_SIZE_PIXEL.p1024x1024:
                    size = new Vector2Int(1024, 1024);
                    break;
                case SCREEN_SIZE_PIXEL.p2048x2048:
                    size = new Vector2Int(2048, 2048);
                    break;
                case SCREEN_SIZE_PIXEL.p4096x4096:
                    size = new Vector2Int(4096, 4096);
                    break;

                //16:9
                case SCREEN_SIZE_PIXEL.p1280x720:
                    size = new Vector2Int(1280, 720);
                    break;
                case SCREEN_SIZE_PIXEL.p1920x1080:
                    size = new Vector2Int(1920, 1080);
                    break;
                case SCREEN_SIZE_PIXEL.p2560x1440:
                    size = new Vector2Int(2560, 1440);
                    break;
                case SCREEN_SIZE_PIXEL.p3840x2160:
                    size = new Vector2Int(3840, 2160);
                    break;

                //CustomscreenSize
                case SCREEN_SIZE_PIXEL.CustomSize:
                    //UpperLimit
                    if(_customSize.x > 4096)
                    {
                        _customSize.x = 4096;
                        Debug.LogWarning("PixelSizeのXを4096に設定しました。");
                    }
                    if(_customSize.y > 4096)
                    {
                        _customSize.y = 4096;
                        Debug.LogWarning("PixelSizeのYを4096に設定しました。");
                    }
                    //UnderLimit
                    if(_customSize.x < 32)
                    {
                        _customSize.x = 32;
                        Debug.LogWarning("PixelSizeのXを32に設定しました。");
                    }
                    if(_customSize.y < 32)
                    {
                        _customSize.y = 32;
                        Debug.LogWarning("PixelSizeのYを32に設定しました。");
                    }
                    size = _customSize;
                    break;                

                //設定されてないSCREEN_SIZE_PIXELが選択された場合
                default:
                    Debug.LogWarning("設定されてないSCREEN_SIZE_PIXELが選択されました。");
                    Debug.LogWarning("解像度 " + size + " で書き出します。");
                    break;
            }
            return size;
        }

        //タイムスタンプ
        private string getTimeStamp(TIME_STAMP type)
        {
            string time;
            //タイムスタンプの設定書き足せます
            switch (type)
            {
                case TIME_STAMP.MMDDHHMMSS:
                    time = DateTime.Now.ToString("MMddHHmmss");
                    return time;
                case TIME_STAMP.YYYYMMDDHHMMSS:
                    time = DateTime.Now.ToString("yyyyMMddHHmmss");
                    return time;
                default:
                    time = DateTime.Now.ToString("yyyyMMddHHmmss");
                    return time;
            }
        }

#endif
    }
}

【2-2】プロジェクトへの導入

1.UnityEditorのProjectタブでメニューを出して「Create」→「C# Script」でScriptを作成します。
 Scriptのファイル名は必ず「ScreenShot」にしてください。別名なだとエラーになります。
2.作成したC#のファイルを開いて、全て削除した後に上記のサンプルコードを全て上書きします。
 using System;の行から } で終わってる行まで全てコピペしてください。
3.ScreenShotのスクリプトを適当なゲームオブジェクトにアタッチしてください。

【2-3】使い方

howto.png

1.UseCameraの部分に撮影に使うCameraを割り当ててください。
2.実行中の場合は F1キーで撮影 実行中じゃない場合も歯車アイコンからメニューを開いて「スクリーンショットを撮影する」を押すと撮影できます。

ScreenSizePixel
プリセットをいくつか用意しました。プリセットに無い場合はCustomSizeを選択して、CustomSizeの欄に画像の解像度を入力してください。
最大解像度は4096、最小解像度は32に制限してあります。

背景色の設定
背景色はAlpha(透明)、CustomColor(選択した色)、Skybox(スカイボックスを撮影する)の3種類から設定できます。

ファイル名の書式設定
タイムスタンプの形式と末尾の文字列を変更できます。
他の書式にする場合はソースコードを直接編集してください。

保存先のフォルダ名
Assetsフォルダ以下に配置されます。(存在しない場合は自動で作成されます)

Gameタブの解像度を指定する方法

gametabu.png
1.Gameタブのあの部分をクリックするとメニューが展開される。
2.+から「Add New Item」を押す。
3.ウインドウでLabel (名前) Width&Height (縦横の解像度)を設定する。
4.プリセットに追加されるので、任意の解像度にできる。

Vtuberの用途的には、Youtubeの基本の解像度を入れておくとよいと思います。
また 128x128 や 1024x1024 等も入れておくと、アイコン作成やテクスチャ作成時に便利です。

参考:【Unity】高解像度のゲーム画面向けにゲームビューを調整する
参考:Youtubeで推奨される解像度とアスペクト比

カメラを移動しながら撮影したい。

【Unity】カメラ移動を制御するスクリプト
上記を参考にしてみてください。キャラクターを撮影するプロジェクトが作れます。
※キー設定が被ってるのでよしなに。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
59