MRが楽しい

MRやVRについて学習したことを書き残す

Unityアプリで画面のキャプチャをするとき一部のオブジェクトを非表示にする

本日は Unity の小ネタ枠です。
Unityアプリで画面のキャプチャをするとき一部のオブジェクトを非表示にする方法について記事にします。

前回記事

以下の記事の続きです。
bluebirdofoz.hatenablog.com

一部のオブジェクトを非表示にする

前回記事で紹介したメインカメラと RenderTexture を利用する方法を使えば、カメラの[Culling Mask]を使って描画するオブジェクトを選択できます。
docs.unity3d.com

サンプルシーンを作って試してみます。
キャプチャで描画したくない Cube オブジェクトの[Layer]を非表示用に追加したレイヤーに設定します。

サンプルスクリプト

以下のサンプルスクリプトを作成しました。
Capture 関数を呼び出すと、一時的に非表示用のレイヤーをカメラの[Culling Mask]から除外してキャプチャを実行します。
・RenderFilterTest.cs

using System;
using System.IO;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class RenderFilterTest : MonoBehaviour
{
    private Camera captureCamera;

    /// <summary>
    /// キャプチャの実行関数
    /// </summary>
    public void Capture()
    {
        CaptureScreenshotByRenderTexture();
    }
    
    private void Start()
    {
        captureCamera = Camera.main;
    }
    
    private void CaptureScreenshotByRenderTexture()
    {
        var ct = this.GetCancellationTokenOnDestroy();
        CaptureScreenshotByRenderTextureAsync(ct).Forget();
    }

    private async UniTask CaptureScreenshotByRenderTextureAsync(CancellationToken ct)
    {
        // 一時的にWithoutCaptureレイヤーを映らなくする
        var uiLayer = LayerMask.NameToLayer("WithoutCapture");
        captureCamera.cullingMask &= ~(1 << uiLayer);

        // 任意のフレームの描画処理が終わるまで待機する
        await UniTask.WaitForEndOfFrame(ct);

        // Cameraの描画領域をRenderTextureとして取り出す
        var rt = new RenderTexture(captureCamera.pixelWidth, captureCamera.pixelHeight, 24);
        var prev = captureCamera.targetTexture;
        captureCamera.targetTexture = rt;
        captureCamera.Render();
        captureCamera.targetTexture = prev;
        RenderTexture.active = rt;

        var screenShot = new Texture2D(
            captureCamera.pixelWidth,
            captureCamera.pixelHeight,
            TextureFormat.RGB24,
            false);
        screenShot.ReadPixels(new Rect(0, 0, screenShot.width, screenShot.height), 0, 0);
        screenShot.Apply();

        // 取り出したTexture2DをPNGに変換して保存する
        var date = DateTime.Now.ToString("yyyyMMdd");
        string filename = $"capture_{date}.png";
        var png = screenShot.EncodeToPNG();
        string path = Path.Combine(Application.persistentDataPath, filename);
        File.WriteAllBytes(path, png);

        // レイヤーの設定を元に戻す
        captureCamera.cullingMask |= 1 << uiLayer;

        Debug.Log($"Capture File : {path}");
    }
}

シーンを再生し、ボタンを押下してキャプチャを実行します。

出力された画像が以下になります。
[Culling Mask]により、Cube オブジェクトが描画されていないことが分かります。