過去の記事では、通常どおりのカメラ空間で2Dゲームの構成を作成しました。その後、「スマートフォン(複雑なアスペクト比)対応とレスポンシブ UI の基本」の記事を書いたとおり、2Dをやるなら Canvas と付き合うようにしたほうが都合よいこともありそうです。
Canvas を使うとき、画面に映る画像の大きさを決める要素として重要なのは
- 画像をインポートしたスプライトデータの設定
pixels per unit
- キャンバスの
Reference Resolution
のパラメーター
両者の関係を整理して、画面にどう映るようになるのか確認していきます。画面の端から端まで、ちゃんと制御して表示できるようになろうという記事です。
Canvas(画面サイズ)の設定
まず、前準備からはじめます。
Canvas の設定値の Render Mode
を Screen Space - Camera
にすると、カメラと Canvas を指定した距離だけ空けてキャンバスを表示してくれます。よくやる設定だと思いますので次に進みます。
カメラに映る(ウィンドウに見える)Canvas の領域は、Canvas Scaler の設定値 UI Scale Mode
が Scale With Screen Size
であるとき、Canvas は Reference Resolution
の値で制御します。
Canvas Scaler の設定値
Reference Pixels Per Unit
の値は影響しません。勘違いしないように!
ここでのサンプルは、画面の縦横比を16:9と仮定することにします。画面にあわせるためには、Reference Resolution
の値を 320x180 のようにします。両者の縦横比が異なると、最初は混乱すると思うので、とりあえずあわせておいたほうがよいと思います。
最適化の観点からだと、Canvas は要素に変更があると Canvas 全体に再解析の処理は走るため 1 最適なドローコールになりません。つまり、ルートが Canvas だとドローコールのコストが大きい可能性があります。対策として、キャンバスをネストする(親 Canvas と子 Canvas の関係を持つ)ことでコンテンツを分離して、独自のジオメトリ、バッチ処理を実行できます。
画面サイズの確認
Canvas のサイズ (Reference Resolution) が 320x180 なら、20x20 のブロックを 16x9 個配置できるはずです。まず、これを確認してみます。
20x20 のブロックの画像を作成して、横に連続して並べることにします。2色のブロックを用意して、めり込んだりしないように画像の端をわかりやすくしました。
画像を Unity の Assets にインポートするとき、画面比率に影響する重要なパラメーターが Pixels Per Unit
です。デフォルトでは 100 に設定されています。この設定の意味は、この画像は1ユニットの幅に対して 100 pixel 詰め込んでください、というようなことになります。
ユニットというのは、最小単位です。ここでは Canvas の
Reference Resolution
の単位になります。
Canvas の 320x180 のサイズに、320 個と 180 個ずつドットを詰め込めるようにするには1ユニットの幅に対して 1 pixel とすればよいので、Pixels Per Unit
の設定値は1になります。
この状態でスプライトを Canvas に追加して、インスペクターから Trasform の Scale を x, y ともに1で設定して画面に詰め込んでいくと、縦横比がとれているのを確認できます。
Pixels Per Unit を1にしない例(1)
仮に、Assets に追加したスプライトの Pixels Per Unit をデフォルトの 100 のまま Canvas にコンポーネントとして追加してみます。インスペクターから Trasform の Scale を x, y ともに1で設定すると、とても小さなスプライトになってしまうのが確認できます。
これは、どういう状態なのか考えてみます。
元々の画像サイズは 20x20 でした。それを1ユニットに対して 100 ピクセル詰め込む設定になっています。つまり1ユニットに だけ表示されている状態だと思われます。
さっそく Canvas 上のコンポーネントの Scale を x, y ともに5倍してみます。おそらくこれで、1ユニットのサイズ(1ピクセルサイズ)になったはずです……が、わかりづらいですね。
さらに20倍すると、ちょうど20ユニットのサイズとなり、つまり1ユニット1 pixel としたコンポーネントと同じサイズになりました。(つまり Scale 100倍です)
Pixels Per Unit を1にしない例(2)
仮に 128x128 の画像を Assets にインポートして、同じく Pixels Per Unit をデフォルトの 100 のまま Canvas にコンポーネントとして追加してみます。
(1)の説明のとおりだと、Canvas に追加したコンポーネントは、1ユニットに対して 1.28 ユニットの大きさで表示されていることになります。
画面に対して、Scale が1のとき 1.28 ユニットの大きさなので、Scale が x のとき1ユニットの大きさなので
これにより、Scale が 0.78125 のとき1ユニットだとわかりました。一応確かめるために20倍して表示してみます。
ブロックと同じサイズになりました。
応用編
たとえば、Canvas のサイズを 32x18 にしてみるパターンを考えてみます。縦横比はあわせてありますが、かなり小さいサイズにも思います。
逆にいえば Canvas の1ユニットを大きく見えるように設計していますので、20x20 の画像を読み込む際は1ユニットの Pixel Per Unit は 20 にするとよいでしょう。
シンプルに取り回せるように、1 タイル = 1 ユニットになるようスケールを設定するのがいいでしょう。
この内容は、「Unity Blog - 2D アートアセットの解像度選択」のとおりですね。
ゲームのメイン部分にあわせた設定にするためにこうしたプロパティがあるのだと思いますが、今までの開発で Windows API や DirectX を使って素直にコードを書いていたなら、1unitは1Pixel というのが自然かもしれません。
参考
-
詳細は長くなるので Unity UI の最適化に関するヒント を参照してみてください。↩