リスト内リストUIをUnityで作るには

# uGUIで要素の高さがバラバラのリストUIを作りたい

たとえば、以下のようなリスト形式のUIを、UnityのuGUIで作りたいとします。

![20220425_vertical_layout_group.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/7e91cbeb-b777-5c2c-ded2-ad55f860deba.gif)

`CheryBlossom` の行の高さが、ボタンクリックによって変わっています。
つまり、ユーザー操作によって、リスト内要素の高さが動的に変化します。

`CheryBlossom` の高さの変化に合わせて、その下にある `Water Daytime` と `[Skybox] EpicSky` の行は、表示位置が上下に変化しています。

こういうUIは、Editor系のツールではよく見かけるものです。

ただ、uGUIで実装するのは意外と難しいので、本記事で解説します！




# 要素の `Height`, `Pos Y` を計算するコードを自前で書くのは大変すぎる

まず、要素の高さ調整は、  `Rect Transform` の `Height` を計算すればできます。

同様に、`Pos Y` を動的に計算すれば、上下位置の調整もできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/e3afe449-8df8-c7d6-1f06-3821a3249848.png)

リスト内の全要素の `Height` と `Pos Y` を計算するスクリプトを書けば、実は目標は達成できるのです。

しかし、この方法は非常に工数がかかります。

要素の追加機能・削除機能・ソート機能等を今後実装する計画があるとしたら、そのすべてで `Height`, `Pos Y` の調整処理を考慮する必要があります。

HTMLの `<ul>` `<li>` みたいに、自動で `Height`, `Pos Y`  を調整してくれる方法はないのでしょうか？



# 要素の `Height`, `Pos Y` は `Vertical Layout Group` が自動で調整してくれる！

自動で `Height`, `Pos Y` を調整してくれる仕組みがちゃんとuGUIにもあります。

それが `Vertical Layout Group` です！



まずは説明のため、要素の高さが動的に変化せず、 `Pos Y` の計算のみを自動化する方法をご紹介します。

![VerticalLayoutGroup1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/dacb2669-b59d-adec-cfcf-c077f0b04661.png)

はじめに、要素の親となるGameObjectに `Vertical Layout Group` をアタッチします。これは、HTMLで例えるなら、 `<ul>` の役割です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/44089fb4-2608-d08e-e214-fe97b62aa7ab.png)

次に要素となるGameObjectに `Layout Element` をアタッチします。HTMLで例えるなら、 `<li>` の役割です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/63dd871c-e081-1f09-f059-758ffeff7e43.png)

`Preferred Height` と `Min Height` に数値を設定することで、要素の高さを固定化できます。

ここまでスクリプトを一切書いていませんが、これだけで、 `Pos Y` の自動計算は実現できます！



# リスト内にリストがある場合

次に、 `Height` の自動化を考えます。

リスト内要素の `Height` を自動的に調整したいというのは、ようするに、リスト内の要素がさらにリストを持っているような状況だと想定できます。

以下の図のような状況です。

![20220425_vertical_layout_group.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/5dd84a0a-1438-35e3-e5f0-1c7f3789e68d.gif)

このように、リスト内リストがある場合は、 `Vertical Layout Group` をネストしましょう！

![VerticalLayoutGroup2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/f85a78ff-37a9-51b6-dfcc-286cc5969975.png)

上図のように、 `Layout Element` と並列で `Vertical Layout Group` を設置しても問題ありません。

私が確認した限り、ネストは3階層までやっても問題なく動作しました。

これで、リスト内要素の `Height` の自動調整もできました！



# リストの高さを要素にフィットさせるには

たとえば以下のように、リスト内要素の数が動的に変化するUIを作るとします。

![ContentSizeFitter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/4b697bf3-53c0-518d-56d5-fed6348f9bb8.png)

上記のように、要素数に応じて、リストの高さをフィットさせなければならないケースがあります。

`Vertical Layout Group` を使えばできそうな気がしますが、実はそれだけでは実現できません。

こういう時は、 `Content Size Fitter` を使いましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/d32f4351-835f-aa38-2acb-3068128f6009.png)

`Vertical Layout Group` を付けているGameObjectに `Content Size Fitter` を付けるだけで、要素にピタッとフィットします！



# 組み合わせたい時はどうすればいいのか？

ここまでご紹介した `Vertical Layout Group`, `Layout Element`, `Content Size Fitter` を組み合わせたくなるケースが出てくると思います。

その際、適切にコンポーネントを設定しないと、互いのコンポーネントの機能が競合して、わけのわからない挙動をするようになります。

それを防ぐためにも、以下の点を見直す必要があります。

## 高さが変化しない要素には `Layout Element` を設定しよう！

まずは、高さが変化しない要素に `Layout Element` をアタッチして、 `Min Height`, `Preferred Height` を設定しましょう！



## 高さが変化する要素には `Vertical Layout Group` を設定しよう！

リストがあるなら、 `Vertical Layout Group` をアタッチしましょう！

リスト内リストがあるなら、そこにもアタッチしましょう！

リスト内リスト内リストがあるなら、そこにもアタッチしましょう！

つまり、配下要素によって高さが変化する要素すべてに `Vertical Layout Group` をアタッチしましょう！



## `Content Size Fitter` はリストの一番親にのみ設定しよう！

最後に、 リストの一番親のGameObjectに `Content Size Fitter` を付けましょう。

それ以外の箇所に設定する必要はありません。（設定すると、Unityから警告が出ます。）



ここまでをまとめると、以下の図のようになります！

![VerticalLayoutGroup3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/6c8f76d5-17e3-0c37-40b9-6acca9119b70.png)



# おまけ: `UI Toolkit` なら自動でレイアウトされる

ここまでuGUIで自動レイアウトをする方法をご紹介してきましたが、 Unity2020.1以降で利用できるUI Toolkitであれば、とくに意識しなくても自動で寸法・配置が調整されます！便利ですね！



# さいごに

本記事作成にあたり、以下のサイトを参考にさせていただきました。ありがとうございました。

- [Unity Documentation / Vertical Layout Group](https://docs.unity3d.com/ja/2019.4/Manual/script-VerticalLayoutGroup.html)

- [テラシュールブログ / 【Unity】uGUIの自動レイアウトが分かりにくいと評判なので解説してみる](https://tsubakit1.hateblo.jp/entry/2017/05/14/163456)

また、本記事に利用しているスクリーンショットは、弊社で運営しているSTYLY Studioというサイトのものです。興味があれば覗いてみてください！

https://styly.cc/ja/manual/scene-create-tutorial/