【Unity】CanvasのOverlayが大きすぎる問題に対応する

Unity の UI を表示するための Canvas ですが、表示モードが3つあって、代表的なのものは、常に最前面に表示する「ScreenSpace - Overlay」と、常にカメラの前に表示する「ScreenSpace - Camera」があります。

カメラの移動に追従して UI を移動させたい場合、ScreenSpace - Camera、常に最前面に表示させたい場合 ScreenSpace - Overlay と使い分けますが、この Overlay のほうは実際のゲーム画面に対して編集サイズが以上に大きすぎる、もしくはゲーム画面が Canvas に対して小さすぎるため UI の編集 ⇔ インゲームの編集を交互に行う場合、Editor 上からいちいち編集領域を移動しなくてはいけなくなり作業が大変しにくくなります。

なので、今回はこの問題を解決するためのコンポーネントを考えてみたので紹介したいと思います。

少し問題が起きるケースがあるけどまぁそういう使い方で問題起きる場合は諦めましょう。

編集中だけScreenSpace - Cameraにする

コンポーネントの条件は以下の通りです。

  • 編集中は 「Screen Space - Camera」
  • 実行中と実機動作は「Screen Space - Overlay 」

コンポーネントの実装

コンポーネントの実装は以下の通りです。

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

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

    // 編集中のモード
    [SerializeField, EnableIf(nameof(_enabled))] RenderMode _editingRenderMode
        = RenderMode.ScreenSpaceCamera;
    // 実行中のモード
    [SerializeField, EnableIf(nameof(_enabled))] RenderMode _playingRenderMode
        = RenderMode.ScreenSpaceOverlay;

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

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

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

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

コンポーネントの使い方

上記のコンポーネントを適当な GameObject に配置します。そうすると以下のような表示になるのでそれぞれ設定していきます。

項目 説明
Enabled チェックを入れているときだけ機能が動作します
Render Camera Screen Space - Camera の時に使用するカメラを指定指定します
Target Canvas List 編集中 - 実行中でモードを変更したい Canvas を指定します
Editing Render Mode 編集中のモード。規定値は Screen Space - Camera
Playing Render Mode 実行中のモード。規定値は Screen Space - Oberlay

で、これを設定するとリストに指定したキャンバスは編集中は Camera

実行中は Overlay になります。

これで、編集中はゲーム画面と同じ大きさに表示されるようになるので少し作業性が向上すると思います。