こんにちは、Unityエンジニアのオオバです。
僕が開発中の「勇者のどうぐ屋さん」には、トップダウン視点のADVパートがあります。
タイルマップを UIのCanvasに重ねて描く 作りで、カメラを寄せるときは、マップを載せたコンテナの拡大率を変えています。
一方、マップを確認するためのフィールドマップビューアは、マップをワールド空間に置いて正投影カメラで見る、別の作りです。
ビューアでキャラを歩かせて確かめていると、「ADVの zoom:2 だと、ここまで映るよね」という会話をしたくなります。
ところが、UIの拡大率とカメラの size は尺度がまったく違うので、同じ数字では話せず、確認のたびに頭の中で換算することになる。
そこで、ビューアのカメラの拡大率を、ADVの拡大率と同じ尺度で表示できるようにしたというお話です。
CanvasScalerの設定が分かれば、カメラの拡大率もADVと同じ物差しで測れる
ビューアの画面を見てみると、HUDの3行目に「拡大率: ADV ×1.00」と、画面に映るマス数が出ています。
拡大して ×2 にすると、映るマスは横9×縦16になります。
- 拡大率の物差しは、ADV側のCanvasScalerの設定から決まる
- カメラのsizeを等倍のときのsizeと比べれば、ADVと同じ拡大率になる
- 前提にしたCanvasScalerの設定値はテストで固定しておく
ADVの画面はCanvasScalerで決まっている
まず、ADV側の画面がどう決まっているかを整理します。
ADVのプレイヤーのprefab(TopDownAdvPlayer.prefab)には、CanvasScalerが次の設定で付いています。
- UI Scale Mode: Scale With Screen Size
- Reference Resolution: 1080×1920
- Screen Match Mode: Expand
1マスの大きさは、キャンバス上で60です。
ここで効いてくるのが Expand の挙動。
Expandはキャンバスが基準解像度より小さくならないように広げるモードで、縦長の画面なら縦方向に、横に広い画面なら横方向に、キャンバスが伸びます。
なので、キャンバスの縦の大きさは次の式で表せます。
- キャンバスの縦 = max(1920, 1080 ÷ 縦横比)
縦横比は「横 ÷ 縦」で、等倍のときに縦に映るマス数は、キャンバスの縦を60で割った値になります。
9:16の画面なら、1080 ÷ (9/16) = 1920 なので、キャンバスの縦はちょうど1920となり、縦に32マス、横は1080 ÷ 60 で18マス映る計算です。
正投影カメラのsizeに換算する
次にビューア側ですが、こちらは1マスを1ワールド単位で置いています。
正投影カメラの orthographicSize は、画面の縦の 半分 が何ワールド単位かを表す値です。
ということは、ADVの等倍と同じ映り方にしたいなら、size は「縦に映るマス数の半分」にすればいい。
- 等倍のsize = max(1920, 1080 ÷ 縦横比) ÷ 60 ÷ 2
カメラを寄せると size は小さくなり、拡大率は size に反比例するので、ADVの尺度での zoom は次の式で出せます。
- zoom = 等倍のsize ÷ 今のsize
コードにすると、次の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 という対応になります。
画面の縦横比ごとに映るマス数
式ができたので、画面の縦横比ごとに映るマス数を並べてみます。
| 画面 | 横 | 縦 |
|---|---|---|
| 9:16 | 18 | 32 |
| iPad(3:4) | 24 | 32 |
| 縦長スマホ(約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描画順の教科書」もおすすめです。
まとめ
本記事では、UIのCanvasで描くADVの画面と、正投影カメラで見るビューアの画面で、拡大率を同じ数字で話せるようにした話をしてきました。
簡単に全体をまとめます。
- Expandのキャンバスの縦を、1920と「1080÷縦横比」の大きいほうとして出した
- 等倍のsizeは キャンバスの縦÷60÷2 として求めた
- zoomを 等倍のsize÷今のsize で換算した
- HUDに拡大率と映るマス数を出し、0キーで等倍に戻せるようにした
- CanvasScalerの設定値をEditModeテストでprefabから読んで固定した
UIとワールド空間で尺度が違うと、ちょっとした確認のたびに換算が挟まります。
一度式にしてHUDに出しておけば、あとは数字を見るだけ。
前提をテストで固定しておけば、UI側の設定が変わっても気付けます。
UIとカメラの縮尺をそろえたい方の参考になればうれしいです。
👉 【Unity基礎】スマホ向けゲームUIの作り方!基本的なUI配置から複数解像度対応まで解説

筆者のXをフォローしよう
- Unity 6000.3.9f1 / URP / uGUI












