【Unity】実行中だけCanvasをOverlayにする

はじめに

Unity の Canvas は特に画面に追従する必要がない場合 Screen Space Overlay にすることが多いと思いますが、Overlay って実際のゲーム画面と比べてサイズが大きすぎて「ゲーム画面を見ながら UI の調整をしたい」みたいなときに少し扱いづらいので「編集中は Screen Space Camera」⇔「 実行中は Screen Space Overlay」 のように切り替えたらいいのでは?というワークフローのためのスクリプトの紹介です。

個人的なスクリプトの用途は「URP でカメラをスタックしたくないけど Canvas は Post Processing の効果を除外する && 編集中は Screen Space Camera で作業したいみたい」用途で使用しています。

確認環境

  • Unity 2021.2.5f1
  • Windows 10

確認は Editor 上で動作後に、Android 向けにビルドして実機で動作確認しています。

実装例

さっそく実装例の紹介です。

EditCameraSettingクラス

まず以下のようにスクリプトをコピペして Unity に取り込んだ後 Hierarchy 上の適当なゲームオブジェクトにアタッチします。

using UnityEngine;

/// <summary>
/// 編集中と実行中でカメラ動作を変更するためのスクリプト
/// </summary>
[ExecuteAlways]
public class EditCameraSetting : MonoBehaviour
{
    // この機能が有効か無効かを表すフラグ
    // true: 有効 / false: 無効
    [SerializeField] bool _enabled;

    // RenderMode.ScreenSpaceCamera の時に使用するカメラ
    // 未設定の時はメインカメラを使用する
    [SerializeField] Camera _renderCamera;
    // モードを変更する対象のCanvas
    [SerializeField] Canvas[] _targetCanvasList;

    // 編集中のモード
    [SerializeField] RenderMode _editingRenderMode = RenderMode.ScreenSpaceCamera;
    // 実行中のモード
    [SerializeField] RenderMode _playingRenderMode = RenderMode.ScreenSpaceOverlay;

    private void Awake()
    {
        if (!_enabled)
        {
            return;
        }

        if (_renderCamera == null)
        {
            _renderCamera = Camera.main;
        }

        if (_targetCanvasList == null || _targetCanvasList.Length == 0)
        {
            return;
        }

#if UNITY_EDITOR
        foreach (var canvas in _targetCanvasList)
        {
            canvas.renderMode =
                UnityEditor.EditorApplication.isPlaying ?
                    _playingRenderMode : _editingRenderMode;
        }
#else
        foreach (var canvas in _targetCanvasList)
        {
            // 実機動作時は強制的にオーバーレイ表示にする
            canvas.renderMode = RenderMode.ScreenSpaceOverlay;
        }
#endif
        foreach (var canvas in _targetCanvasList)
        {
            if (canvas.renderMode == RenderMode.ScreenSpaceCamera)
            {
                canvas.worldCamera = _renderCamera;
            }
        }
    }
}

使い方

ゲームオブジェクトにアタッチすると以下のようにインスペクターが表示されます。

f:id:Takachan:20211210174018p:plain

項目 意味
Enabled チェックを入れると処理が有効になります
Render Camera Canvas を表示するカメラを指定します
Target Canvas List 対象の Canvas を指定します。複数指定可
Editing Render Mode 編集中の Canvas のモード(デフォルトは Screen Space Camera)
Playing Render Mode 実行中の Canvas のモード(デフォルトは Screen Space Camera)

補足:

  • 設定に関係なく実機で実行したときは Overlay 固定になります
  • Overlay の Canvas の前後関係は Z ではなく Sorting Layer か Order in Layer で指定してください

動作例

編集中

f:id:Takachan:20211210174241p:plain

実行中

f:id:Takachan:20211210174305p:plain

状態毎に変わっている事が確認できます。