テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】逆引き自動レイアウトのトレーニング。UIをLayoutGroupで並べる

f:id:tsubaki_t1:20170615020246j:plain

今回は自動レイアウトの動作を把握するために、色々とトレーニングしてみました。

自動レイアウトでUIを並べる

UIの要素を並べる場合、HorizontalLayout GroupやVertical Layout Groupといったレイアウト調整機能を使用するのが便利です。

ただ、この動作は割とわかりにくいと評判(主観)です。なので、下の記事である程度の解説を行いましたが、今回は実際に色々と並べてみようと思います。

tsubakit1.hateblo.jp

なお、今回のレイアウトシステムは全てHorizontalLayoutを使用しますが、動作的にはVertical Layoutも似たようなものです。

UIのサイズが固定、もしくは親に合わせて子のサイズが変動する場合は、簡単

UIのサイズが固定だったり、親のサイズに合わせて子のサイズが変動するような場合、並べるのは割と楽です。

Imageを並べる(左から詰める)

単純にSpriteを並べる場合です。並べる際には、左から順番に詰めるように並べます。

f:id:tsubaki_t1:20170614233730g:plain

  1. 適当にCanvasを作る。
  2. CanvasにHorizontalLayoutGroupを設定する。
    その際、Control Child SizeやChild Force Expandは外す
    Child AlignmentはMiddle Left(左の中央)を設定
  3. Image付きSpriteを作る(×沢山)

f:id:tsubaki_t1:20170614234007j:plain

これで、左からUIの大きさに合わせて詰めて並べる挙動になります。生成するImageの大きさ調整を行う設定になっていないので、レイアウトによっては画面外にUIが飛び出したり、逆に余白が生まれるといった事になるかもしれません。

なお、この設定ではRectTransformのサイズを見ます。つまり、UIの大きさによって詰め具合が変わります。

f:id:tsubaki_t1:20170614234810g:plain

また各Imageにスペースが欲しい場合は、Spacingを少し増やします。

 

Imageを並べる(等間隔)

f:id:tsubaki_t1:20170614235312g:plain

UIを等間隔に生成します。

  1. 適当にCanvasを作る。
  2. CanvasにHorizontalLayoutGroupを設定する。
    その際、Child Force Expandにチェックを入れる
    Child AlignmentはMiddle Center(中央)を設定
  3. Image付きSpriteを作る(×沢山)

Child Force Expandにチェックが入っている(初期設定)ので、等間隔に並びます。入り切らない場合、枠の外にはみ出ます。Control Child Sizeにチェックが入っていないので、Imageの大きさは変化しません。

f:id:tsubaki_t1:20170614235645j:plain

高さにフィットしたUIを並べる

f:id:tsubaki_t1:20170615000315g:plain

レイアウトは必ずしも固定とは限りません。
例えばAndroid端末のアスペクト比はカオスですし、iPadはアプリを分割して起動出来ますし、Androidもアプリをウィンドウモードで起動できます。

ので、UIの高さもある程度フレキシブルな事が望ましいといえば望ましいです。

  1. 適当にCanvasを作る。
  2. CanvasにHorizontalLayoutGroupを設定する。
    その際、Child Force ExpandとControl Child SizeのY軸にチェックを入れる
    Child AlignmentはMiddle Left(中央左)を設定
  3. Image付きSpriteを作る(×沢山)

f:id:tsubaki_t1:20170615000759j:plain

Y軸はUIの大きさと一致するレベルで広がりますが、X軸のサイズはRectTransformのサイズで動きます。

 

なお、上下に余白を付けたい場合はPaddingを設定します。

f:id:tsubaki_t1:20170615000941j:plain

 

大きさが固定なUIを並べる

大きさが固定なUI(幾つかのImageを組み合わせたもの)を並べます。

f:id:tsubaki_t1:20170615001522g:plain

まず下のようなUIを作成します。割とごく普通の、よくある構成のUIです。RectTransformの下にImageが3つ。

f:id:tsubaki_t1:20170615001819j:plain

後は「Imageを並べる(左から詰める)」と同じ要領です。

 

  • 適当にCanvasを作る。
  • CanvasにHorizontalLayoutGroupを設定する。
    その際、Control Child SizeやChild Force Expandは外す
    Child AlignmentはMiddle Left(左の中央)を設定
  • UIを作る(×沢山)

上記の設定ではRectTransformの設定でオブジェクトが並べられるので、レイアウトはシンプルに並びます。

勿論、大きさを変更することも可能です。

f:id:tsubaki_t1:20170615212141g:plain

子の大きさを元にUIのサイズが変動する場合は、面倒くさい

逆に子の大きさが固定ではなく、子の大きさに従ってUIのサイズが決まる場合、割と面倒な事になります。具体的には、UIの大きさを自動レイアウトで調整する必要性が出てきます。

子のUIの大きさが変動するUIを並べる(子のmin=Perferred)

「子のUIの大きさが変動するUI」を並べてみます。まずはmin = Perferred…つまり大きさの基準がImageの場合です。

f:id:tsubaki_t1:20170615005624g:plain

この動作では、UIの大きさを変更してしまえば「大きさが固定なUIを並べる」と同じように設定出来るのですが、それが難しい場合はLayout Groupに大きさを調整してもらいます。

  1. 適当にCanvasを作る。
  2. CanvasにHorizontalLayoutGroupを設定する。
    その際、Control Child Sizeにチェックを入れ、Child Force Expandのチェックは外す
    Child AlignmentはMiddle Left(左の中央)を設定
  3. UIを作り、UIのトップはHorizontalLayoutGroupを設定。Control Child Sizeにチェックを入れる
  4. UIの次の階層にHorizontalLayoutGroupを設定。Control Child Sizeにチェックを入れない。4の子にImageを作成。適当な大きさにする

f:id:tsubaki_t1:20170615010723g:plain

Control Child Sizeが入っていると、子のPerferredのサイズを元にRectTransformを変更します。

子から親へPerferredの値にPaddingを足してPerferredのサイズを調整、親から子にPerferredの値を元にRectTransformを調整しています。なので、最後(大きさの変わるUI)の親にはControl Child Sizeにチェックが入っていません。

子のUIの大きさが変動するUIを並べる(子のmin≠Perferred)

次にlayout elementのminとperferredが一致しない場合です。

f:id:tsubaki_t1:20170615004934g:plain

具体的に言えばTextです。Textはperferredは文字が全て入るサイズになりますが、minの大きさは0です。またRectTransformとperferredのサイズが一致しない点もあります。

 

  1. 適当にCanvasを作る。
  2. Canvasの子を作成
  3. 2のオブジェクトにHorizontalLayoutGroupを設定する。
    その際、Control Child Sizeにチェックを入れ、Child Force Expandのチェックは外す。
    Child AlignmentはMiddle Left(左の中央)を設定
  4. UIを作り、UIのトップはHorizontalLayoutGroupを設定。Control Child Sizeにチェックを入れる
  5. UIの次の階層にHorizontalLayoutGroupを設定。Control Child Sizeにチェックを入れる。
  6. 5の子にTextを作成

f:id:tsubaki_t1:20170615012051g:plain

「子のUIの大きさが変動するUIを並べる(子のmin=Perferred)」と異なり、UIの大きさはTextが生成するPerferredの値を元にレイアウトを調整します。なので、下から二番目のLayoutGroupもControl Child Sizeにチェックが入っています。

 

ただ忘れてはいけないのがminのサイズは0という事です。なので、範囲内にUIが入り切らなかった場合、UIの大きさが変動してしまいます。

f:id:tsubaki_t1:20170615013256g:plain

これを回避するアイディアで思いつくのは二つ。

一つはContent Size FitterでPerferredと同じ大きさに一番親のオブジェクト(今回で言うならCanvasの下のRoot)のサイズを変更してしまう事。これで「入り切らなくてUIが縮まる」事は無くなります。なにせ、足りなくなったら親が大きくなる訳ですから。

もう一つが、minのサイズをPerferredのサイズにしてしまう事。これでminが0では無いので圧縮されることはなくなります。

gist.github.com

f:id:tsubaki_t1:20170615014251j:plain

これでオブジェクトが隅っこに到達しても、UIが潰れる事は無くなりました。

f:id:tsubaki_t1:20170615014759g:plain

 

感想

自動レイアウトの復習でした。

とりあえず「任意のサイズのUIを並べる」だけなら簡単なんですが、Textのように子のサイズを元にレイアウトを決める場合、面倒なことになります。

印象としては下な感じです。

  • 子から親にサイズ情報を渡し、それを元に親レイアウトは自身のサイズを決める
  • 親レイアウトグループが子のRectTransformを調整する

関連

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp