ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

Unity学習#26-2 LayoutGroupを2重にすると LayoutGroup が Element の合計サイズにフィットする原理 (Unity 2019.4.4f1)

#26 の実装にあたって、少しLayoutについて調べた内容を備忘のためにまとめます。テキストやイメージに合わせて枠がスケールするようにしたい場合に、LayoutGroup を2重にします。どうしてLayoutGroupを2重にすることで枠をスケールできるようになるのかについて分かった範囲でまとめます。

<目次>


記事の大半は、前回#26-1の記事を参考にしています。
tomo-mana.hatenablog.com

概要

テキストやイメージに合わせて枠がスケールするようにするには、以下のようにします。(コーディング不要です)

(1) 枠用のゲームオブジェクトの親に、ダミーのLayoutGroupを配置します。(LayoutGroup2段構え)
(2) ダミーのLayoutGroup の Control Child Size = ON、枠用のLayoutGroup の Control Child Size = OFF にします。

f:id:tomo_mana:20210212231616p:plain
Hierarchy
f:id:tomo_mana:20210212231636p:plain
Inspector


以下、動作原理を簡単にまとめます。

LayoutGroup

1段(Group→Element)

LayoutGroup が LayoutElement を整列する手順は以下になります。

f:id:tomo_mana:20210210231956p:plain
LayoutGroup → LayoutElement

LayoutGroup が整列を行う時、LayoutRebuilder が全体に指示を出します。

(1) LayoutGroup の全ての LayoutElement に対して、CalculateLayoutInputHorizontal/Vertical() をコールします。LayoutElement は min, preferred, flexible width/height を計算します。このコールは子、親の順に呼ばれます。

(2) LayoutGroup も LayoutElement である必要があり、LayoutGroup がこの関数をコールされたときは、自分の子の min, preferred, flexible width/height を取得します。

(3) 次に、(LayoutGroup に属する全ての)LayoutGroup に対して SetLayoutHorizontal/Vertical() をコールして、先ほど取得したmin, preferred, flexible width/height を使って、子の位置(Anchor、Pos)を決めます(整列)。

この処理のポイントは、大きさを変更するためには RectTransform を更新する必要があり、RectTransform が更新されるのは LayoutGroup に属する LayoutElement だけ ということです。(LayoutElement は、大きさの情報を保持しているだけ)

2段(Group→Group→Element)

LayoutGroup を2重にしたときの処理は以下のようになります。

f:id:tomo_mana:20210211000251g:plain
LayoutGroup → LayoutGroup → LayoutElement

処理の順番は先ほどと同じです。違いは、

(4) 子供のLayoutGroupは、親のLayoutGroupから見ると、LayoutElementです。そのため、親のLayoutGroupは、子供のLayoutGroupのサイズ情報を使って、子供のRectTransformを更新します。

(5) 孫階層については1段の時と同じです。

そのため、親を子のサイズに合わせたい場合は、親の上にもう一段ダミーの親を挟めばよいことになります。

ただし、もう一つ条件があります。Control Child Size の指定です。

Control Child Size

LayoutGroup の Preferred Width/Height の計算

ControlChildSize LayoutGroupのPreferredSize
OFF 子LayoutElementのRectTransformの合計
ON 子LayoutElementのPreferredWidth/Heightの合計

※上記に、自身の padding(四隅に入れるスペース)+ spacing(LayoutElement間に入れるスペース)を足したもの。

表示サイズ(RectTransform)の計算

ControlChildSize LayoutGroupの表示サイズ LayoutElementの表示サイズ
OFF LayoutGroupのRectTransform LayoutElementのRectTransform
ON(親 > 子) LayoutGroupのRectTransform LayoutGroupに従って圧縮
ON(親 < 子) LayoutGroupのRectTransform LayoutElementのPreferredWidth/Height

※Control Child Size を有効にしたとき、子のRectTransformのwidth/heightは親によって決められます。

子の大きさで親をスケールさせる条件

そのため、子の大きさで親をスケールさせるには、以下のようにします。
孫は自分で大きさを決めたい → 子のControl Child Size は OFF
子は孫のサイズで決めたい → 親のControl Child Size は ON

f:id:tomo_mana:20210213222233p:plain
各階層のRectTransformの大きさの決定

※LayoutElementのpreferredの計算は別の記事にまとめます。

参考(シーケンス図)

1段

f:id:tomo_mana:20210208013014p:plain
f:id:tomo_mana:20210208013026p:plain

2段

f:id:tomo_mana:20210208235036p:plain
f:id:tomo_mana:20210208235050p:plain
f:id:tomo_mana:20210208235100p:plain