こんにちは、Unityエンジニアのオオバです。

お悩みさん
お悩みさん
  • UIのCanvasで描いた画面と、正投影カメラで見た画面の縮尺を合わせたい
  • CanvasScalerのExpandで画面に何マス映るのか計算したい
  • CanvasScalerの設定を変えたときにコード側の定数がずれるのが怖い
  • オオバ
    オオバ
    本記事ではこれらの悩みを解決します。

    僕が開発中の「勇者のどうぐ屋さん」には、トップダウン視点のADVパートがあります。

    タイルマップを UIのCanvasに重ねて描く 作りで、カメラを寄せるときは、マップを載せたコンテナの拡大率を変えています。

    一方、マップを確認するためのフィールドマップビューアは、マップをワールド空間に置いて正投影カメラで見る、別の作りです。

    ビューアでキャラを歩かせて確かめていると、「ADVの zoom:2 だと、ここまで映るよね」という会話をしたくなります。

    ところが、UIの拡大率とカメラの size は尺度がまったく違うので、同じ数字では話せず、確認のたびに頭の中で換算することになる。

    そこで、ビューアのカメラの拡大率を、ADVの拡大率と同じ尺度で表示できるようにしたというお話です。

    ※2026年10月13日、Claude Codeと一緒に開発した内容です

    CanvasScalerの設定が分かれば、カメラの拡大率もADVと同じ物差しで測れる

    ビューアの画面を見てみると、HUDの3行目に「拡大率: ADV ×1.00」と、画面に映るマス数が出ています。

    ADV ×1(9:16で横18×縦32マス)

    ADV ×1(9:16で横18×縦32マス)

    拡大して ×2 にすると、映るマスは横9×縦16になります。

    ADV ×2(横9×縦16マス)

    ADV ×2(横9×縦16マス)

    今回のポイント
    • 拡大率の物差しは、ADV側のCanvasScalerの設定から決まる
    • カメラのsizeを等倍のときのsizeと比べれば、ADVと同じ拡大率になる
    • 前提にしたCanvasScalerの設定値はテストで固定しておく

    ADVの画面はCanvasScalerで決まっている

    まず、ADV側の画面がどう決まっているかを整理します。

    ADVのプレイヤーのprefab(TopDownAdvPlayer.prefab)には、CanvasScalerが次の設定で付いています。

    1マスの大きさは、キャンバス上で60です。

    ここで効いてくるのが Expand の挙動。

    Expandはキャンバスが基準解像度より小さくならないように広げるモードで、縦長の画面なら縦方向に、横に広い画面なら横方向に、キャンバスが伸びます。

    なので、キャンバスの縦の大きさは次の式で表せます。

    縦横比は「横 ÷ 縦」で、等倍のときに縦に映るマス数は、キャンバスの縦を60で割った値になります。

    9:16の画面なら、1080 ÷ (9/16) = 1920 なので、キャンバスの縦はちょうど1920となり、縦に32マス、横は1080 ÷ 60 で18マス映る計算です。

    正投影カメラのsizeに換算する

    次にビューア側ですが、こちらは1マスを1ワールド単位で置いています。

    正投影カメラの orthographicSize は、画面の縦の 半分 が何ワールド単位かを表す値です。

    ということは、ADVの等倍と同じ映り方にしたいなら、size は「縦に映るマス数の半分」にすればいい。

    カメラを寄せると size は小さくなり、拡大率は size に反比例するので、ADVの尺度での zoom は次の式で出せます。

    コードにすると、次の2つのメソッドだけです。

    public static float AdvBaseSize(float aspect)  
    {
        float canvasHeight = Mathf.Max(AdvReferenceResolution.y, AdvReferenceResolution.x / aspect);  
        return canvasHeight / TopDownConstant.TileSize * 0.5f;  
    }
    public static float ToAdvZoom(float size, float aspect) => AdvBaseSize(aspect) / size;  
    

    AdvReferenceResolution はCanvasScalerと同じ1080×1920、TopDownConstant.TileSize は60。

    9:16の画面なら、等倍のsizeは 1920 ÷ 60 ÷ 2 = 16 になり、size を8まで寄せれば ×2 という対応になります。

    画面の縦横比ごとに映るマス数

    式ができたので、画面の縦横比ごとに映るマス数を並べてみます。

    ADV等倍(×1)で画面に映るマス数
    画面横縦
    9:161832
    iPad(3:4)2432
    縦長スマホ(約9:19.5)18約39

    iPadのように横に広い画面では、縦は1920のまま、横が1440まで広がって24マス。

    縦長スマホは反対に、横は18マスのまま、縦が伸びて約39マス映ります。

    Expandの「基準より小さくならない」性質が、そのまま数字に出ているのが分かりますね。

    9:16の値は、UnityのGame画面を9:16にして目で確認したもので、冒頭のキャプチャで ×1 が横18×縦32、×2 が横9×縦16になっているのがその結果です。

    iPadと縦長スマホの値は、計算とEditModeテストで確かめています。

    ビューアのHUDとショートカット

    ビューアのHUDには、拡大率と映るマス数を並べて出すようにしました。

    たとえば ×1.5 まで寄せると、次のように表示されます。

    「拡大率: ADV ×1.50 / 画面に映るマス: 横12.0×縦21.3」

    横18 ÷ 1.5 = 12、縦32 ÷ 1.5 ≒ 21.3 なので、計算どおりです。

    もう1つ、0 キーでADVの等倍に戻せるようにしました。

    ホイールで拡大縮小していると、等倍がどこだったか分からなくなりますよね。

    ワンキーで基準に戻れると、比べるときの安心感がまるで違います。

    CanvasScalerの前提をEditModeテストで固定する

    ここで1つ気になったのが、基準解像度の1080×1920やExpandという設定を、コード側に定数で持っている点です。

    UI側でCanvasScalerの設定を変えると、ビューアの計算は 黙ってずれる うえにエラーも出ないので、気付くのはだいぶ後になりそう。

    そこで、EditModeテストでprefabを読み込み、CanvasScalerの値とコードの定数を比べるようにしました。

    Component scaler = prefab.GetComponentsInChildren<Component>(true).Single(c => c.GetType().Name == "CanvasScaler");  
    var serialized = new SerializedObject(scaler);  
    Assert.AreEqual(FieldMapViewerCamera.AdvReferenceResolution, serialized.FindProperty("m_ReferenceResolution").vector2Value);  
    Assert.AreEqual(1, serialized.FindProperty("m_ScreenMatchMode").enumValueIndex); // Expand  
    

    比べているのは、m_ReferenceResolution、m_UiScaleMode、m_ScreenMatchMode の3つ。

    CanvasScalerは型名で探し、値は SerializedObject 経由で読んでいます。

    この書き方なら、テストのasmdefが UnityEngine.UI を参照していなくても読めるので、テスト用のasmdefに参照を足さずに済みました。

    UIの設定を誰かが変えたらテストが落ちて教えてくれるので、人間が覚えておく必要がなくなるのは大きいですね。

    ついでに:正投影カメラでのSpriteRendererの前後

    ビューアでキャラや動物を歩かせていて、もう1つ手を入れたところがあります。

    正投影カメラでは、同じ sortingOrder の SpriteRenderer 同士だと、Zが小さい(カメラに近い)ほうが手前に描かれます。

    トップダウンの画面では画面の下にいるキャラほど手前に見えてほしいので、キャラと動物のZを「Y × 0.01」にしました。

    画面の下にいるほどYが小さくなり、Zも小さくなるので、手前に描かれるという仕組みです。

    描画順の考え方をもっと体系的に知りたい方には、僕が執筆した「Unity描画順の教科書」もおすすめです。

    Unity描画順の教科書
    Unityの描画順を体系的に学べる入門書。ゲーム開発中に登場するさまざまなオブジェクトの描画順を思ったとおりに制御してみ...
    詳しくはこちら
    Unity描画順の教科書

    まとめ

    本記事では、UIのCanvasで描くADVの画面と、正投影カメラで見るビューアの画面で、拡大率を同じ数字で話せるようにした話をしてきました。

    簡単に全体をまとめます。

    今回のまとめ
    • Expandのキャンバスの縦を、1920と「1080÷縦横比」の大きいほうとして出した
    • 等倍のsizeは キャンバスの縦÷60÷2 として求めた
    • zoomを 等倍のsize÷今のsize で換算した
    • HUDに拡大率と映るマス数を出し、0キーで等倍に戻せるようにした
    • CanvasScalerの設定値をEditModeテストでprefabから読んで固定した

    UIとワールド空間で尺度が違うと、ちょっとした確認のたびに換算が挟まります。

    一度式にしてHUDに出しておけば、あとは数字を見るだけ。

    前提をテストで固定しておけば、UI側の設定が変わっても気付けます。

    UIとカメラの縮尺をそろえたい方の参考になればうれしいです。

    👉 【Unity基礎】スマホ向けゲームUIの作り方!基本的なUI配置から複数解像度対応まで解説

    オススメ記事
    検証環境