LoginSignup
3
4

More than 1 year has passed since last update.

【uGUI自動レイアウト】ContentSizeFitterとLayoutGroupを正しく設定して、「動的に大きさが変化するTextコンポーネント」を実現する

Last updated at Posted at 2022-11-15

TL;DR

子にContentSizeFitterを設定したときは、親のLayoutGroupのControlChildSizeをオフにすること。

動機

「Textコンポーネントを使って動的に大きさが変化するUI」(行の増えていくログ機能など)を作りたかった。
しかし、自身のUIサイズを調整するContentSizeFitterを使うとUnityEditorで警告がでて無効になったり、ContentSizeFitterを使わないと求める機能が実現できなかったりした。

公式ドキュメント(自動レイアウト - Unity マニュアル)を読んでもよくわからず...

こちらを見たところやっと理解できたので、やりたかったことに必要な原理の理解と設定方法をまとめた。
uGUIの自動レイアウトを根っこのほうから理解する|fuqunaga|note

原理:uGUIのレイアウト処理

uGUIの自動レイアウトを根っこのほうから理解する|fuqunaga|note  より抜粋・要約

uGUIの2種類のレイアウト処理方法

処理の流れ 処理
通常のレイアウト 親 -> 子 親の矩形(RectTransform)をもとに子の矩形が一意に決まる。
自動レイアウト 親 <- 子 子の情報をもとに自分自身や子のRectTransformを編集する。

自動レイアウトの例)「Text コンポーネントなど内容によってサイズが変わるUIがはみ出さないように親のUIのサイズを広げる」など

自動レイアウト

自動レイアウトは以下の2つの要素から成る。

LayoutElement: 自身のサイズについての「要望」

  • 要望なのでこれ単体では特になにも変化しない
  • LayoutElementとして扱われるのは ILayoutElement を継承するコンポーネント全て
    • つまり、 LayoutElement コンポーネント だけでなく、TextImage もLayoutElementとして自身のサイズの要望を伝える。

LayoutController: RectTransform の編集者

  • 「要望」を元に(自身or子の)RectTransformを編集する。
  • 複数のレイアウトコントローラーの編集が衝突しないように Editor 上でのサポートがある。
    • (つまり、複数LayoutControllerで1つのRectTransformを編集してはいけない
  • 主なLayoutControllerの挙動
    • ContentSizeFitter: 自身のサイズをレイアウトエレメントの Min または Preferred にする。
    • LayoutGroup: Control Child Size が OFF のときは(子の)サイズの変更はなく位置だけ整列する。

「Textコンポーネントを使って動的に大きさが変化するUI」の設定例

GameObjectのヒエラルキー

以下のヒエラルキーを想定して設定した。
image.png

各GameObjectの設定値

  • TextContainerのVerticalLayoutGroupは、ControlChildSizeをOFFにする。
    • つまり、子(text)のサイズを編集しない。
  • Text11はTextとContentSizeFitterを設定。
    • つまり、Textコンポーネントのサイズ要望を、自身のContentSizeFitterで設定する。

image.png

※VerticalLayoutGroupは、両方のインターフェースを実装してるので、両方の役割を持つ

まとめ

子にContentSizeFitterを設定したときは、親のLayoutGroupのControlChildSizeをオフにすること。
複数のLayoutControllerが同時にRectTransformのSizeを編集しないようにするため。

備考:ILayoutElement/ILayoutControllerの実装

公式ドキュメント(Unity - Scripting API: LayoutGroup など)を見て、厳密にはILayoutElement/ILayoutControllerがどのように実装されているか、クラス図をおこして確認した。

自動レイアウト周りの実装のクラス図

VerticalLayoutGroupは、(LayoutGroup, HorizontalOrVerticalLayoutGroupを経由して)ILayoutElement/ILayoutControllerの両方を実装しているのが分かる。

ButtonはLayoutGroup・LayoutElementどちらでもない。

PUMLコード
@startuml

interface ILayoutController
interface ILayoutElement
interface ILayoutGroup
' interface ILayoutSelfController


ILayoutController <|.. LayoutGroup
ILayoutElement <|.. LayoutGroup
ILayoutGroup <|.. LayoutGroup

LayoutGroup <|-- HorizontalOrVerticalLayoutGroup
HorizontalOrVerticalLayoutGroup <|-- VerticalLayoutGroup
HorizontalOrVerticalLayoutGroup <|-- HorizontalLayoutGroup


' ILayoutSelfController <|.. ContentSizeFitter
ILayoutController <|.. ContentSizeFitter

ILayoutElement <|.. LayoutElement
ILayoutElement <|.. Text
ILayoutElement <|.. Image

Selectable <|-- Button

@enduml
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4