2023年12月31日日曜日

【Unity】アスペクト比を維持して固定値を使わずに整列させる

アスペクト比を維持して固定値を使わずに整列させる方法をなんと2つも説明します。

問題設定

まずは目指す状態について説明します。

上の画像では半透明の範囲に本の画像とその白背景のセットが2つ描かれています。また白背景は正方形で、本の画像はその中に収まります。つまり、本+白背景の縦横比は1:1になります。

整列の設定を上手く施すことで、中身を増減させても自動的に間隔を調整してくれます。実際私は、以下の画像を作る時に位置や大きさを入力しませんでした。


以降の章でこの自動整列の設定方法について解説します。

なお、この記事では横に整列させる方法を解説しますが、Horizontal←→Vertical、Width←→Heigh(t)と適宜変換すれば縦にも同様に整列させられます。

共通部分

自動整列を実装する方法は複数ありますので、まずはそれらの共通部分について説明します。

上の画像は本の画像と白背景のセットが2つある場合のヒエラルキーです。

上のヒエラルキーに登場するCanvas内のGameObjectが有するComponentを以下に示します。

  • Area(親オブジェクト)
    • Horizontal Layout Group
      • 横に整列させるやつ。今回の主役
      • Control Child SizeのHeighをTrueにして、子の縦の長さを親に合わせるようにする
      • Child Force ExpandはいずれもTrueに
    • Image
      • 半透明なやつ
  • GameObject 1(子オブジェクト)
    • 今は何もつけない
  • Background(孫オブジェクト)
    • Image
      • ただの白背景なので、Spriteは何も入れない
  • Book(孫オブジェクト)
    • Image
      • 本の画像を挿す
      • 画像の比を維持するため、Preserve Aspectをtrueに

これらに追加でComponentを加えるケースもあります。

Aspect Ratio Filterを子オブジェクトにつける方法

Areaに紐づける"Horizontal Layout Group"の"Control Child Size"のHeighがTrueになっている場合(上の画像)、子のオブジェクト(GameObject1)のHeightには何も入力できない状態になります。"Control Child Size"はその名の通り、子のWidthやHeightを親が決定するかどうかのフラグであり、Trueになると子オブジェクトに対するWidth/Heightの入力を受け付けなくなります。

子オブジェクトにてHeightが入力できない状態

本と白画像のセットの縦横比は1:1にするためには、Widthの値をHeightからコピーしてくる必要があります。そこで、子オブジェクトに"Aspect Ratio Filter"を適用します。

Aspect Ratio Filterはそのオブジェクトのアスペクト比を自動で決定するためのComponentです。Aspect Modeで"Height Controls Width"を選択すると、WidthがHeightの値から自動入力されます。このように設定することで、本+白背景を複製しても同じ親にある限り上手に間隔を作ってくれます。

しかし残念なことに、子オブジェクト以下をPrefab化してスクリプト上から複製すると自動整列が機能しません。Aspect Ratio FilterとHorizontal Layout Groupが共存すると発生する問題のようで、入力をロックする箇所が異なっていても動作しないようです(実際警告が出てる)。Aspect Ratio Filterが先にWidthやHeightをロックすることで後のLayoutGroupが動作できなくなり、機能しないのではないかと睨んでいます。Prefabから生成する場合は次の方法を試してみてください。

Aspect Ratio Filterを孫オブジェクトにつける

代替案として、子オブジェクトの代わりに孫オブジェクト(Background)にAspect Ratio Filterをつけることでも自動整列が可能です。その際、Aspect Modeを"Envelope Parent"に設定しましょう。Envelope Parentモード下では、元々設定していた孫オブジェクトの大きさを子の大きさによって拡大することが可能になります。

孫オブジェクト(Background)のComponent

上の画像ではW Deltaに82.79999と入力されています。これは親オブジェクトのHeightが182.79999で、元々設定されていた子オブジェクトのWidthが100であり、Envelope Parentによって引き伸ばされた分がW Deltaに入力されます。

この方法ではPrefabから生成しても自動整列が機能します。Aspect Ratio FilterとHorizontal Layout Groupが同じ箇所をロックすることもないので、警告も発生しません

余談

自動整列問題がややこしいのは、WidthやHeightを画面の大きさに応じて変化させようとするからです。WidthやHeightに固定値を入力させられれば、Layout Elementなどを利用してもっとわかりやすく自動整列を実装できます。まずは画面のサイズを最初に決めて、WidthやHeightに固定値を入力させるのが良いと思います(一敗)。

まとめ

  • XXX Layout Groupを親に設定して整列させる
  • Aspect Ratio Filterを子か孫に設定してアスペクトを維持させる
  • 画面のサイズは最初に決めよう


以上です。

【ゲーム製作】日◯簿記の問題集で家を確保するゲーム

日◯簿記の問題集で家を確保するゲームを公開しました!

URL: https://unityroom.com/games/boki-warashibe

よかったら遊んでください。(偉い人に怒られたら消します)