Scroll ViewとLayout Groupでリストを作ろう【Unityスタートガイド9-6】

アイテムの一覧、ステージ選択、ランキング・・・項目がたくさんあって画面に入りきらないときは、スクロールできるリストにします。今回はScroll Viewと、部品を自動できれいに並べてくれるLayout Groupを組み合わせて、アイテムリストを作ってみましょう!

目次

この記事で学べること

  • Scroll Viewの作り方と、中のしくみ
  • Layout Group(Vertical / Horizontal / Grid)で自動で並べる方法
  • Content Size Fitterで、中身に合わせて大きさを変える方法
  • スクリプトからリストの項目を増やす方法

前提知識

Scroll View(スクロールできる枠)

Scroll Viewを作る

  • Canvasを右クリック>UI>Scroll View
  • 四角い枠と、右と下にスクロールバーが表示される

Scroll Viewのしくみ

  • Scroll View:全体。Scroll Rectコンポーネントでスクロールの動きを管理する
  • Viewport:見える範囲の「窓」。この外にはみ出した部分は隠れる
  • Content:スクロールする中身。リストの項目はContentの子に入れる
  • Scrollbar Horizontal / Vertical:横と縦のスクロールバー

Contentが窓(Viewport)より大きいときだけ、スクロールできます。

縦だけにスクロールさせる

  • Scroll RectのHorizontalのチェックを外す(横にはスクロールしない)
  • 使わないScrollbar Horizontalは削除し、Scroll RectのHorizontal Scrollbarの欄が「None」になっていることを確認
  • Scroll Sensitivity:マウスホイール1回でスクロールする量。初期値だと遅いと感じたら、大きくする

Layout Groupで自動で並べる

項目を1つずつ手で並べるのは大変です。Layout Groupを付けると、子の部品を自動できれいに並べてくれます。

コンポーネント並べ方
Vertical Layout Group縦に1列
Horizontal Layout Group横に1列
Grid Layout Groupマス目(タイル状)

Vertical Layout Groupを付ける

  • Contentを選び、Add Component>Layout>Vertical Layout Group
  • Padding:まわりの余白
  • Spacing:項目どうしのすき間
  • Child Alignment:どこに寄せて並べるか(Upper Center:上・中央)
  • Control Child Size / Child Force Expand:子の幅や高さを、Layout Groupがそろえるかどうか
    • 縦に並べるリストなら、Widthにだけチェックを入れると、横幅がそろって高さは項目のままになります

子に置いたボタンのRect Transformの位置は、Layout Groupが決めるので手で動かせなくなります(Inspectorがグレーになります)。

Content Size Fitterで中身に合わせる

項目が増えたら、Contentの高さも自動で伸びてほしいですよね。そのためにContent Size Fitterを付けます。

  • Contentに、Add Component>Layout>Content Size Fitter
  • Vertical Fit:Preferred Sizeにする

これで、子の数に合わせてContentの高さが自動で変わり、はみ出した分がスクロールできるようになります。

項目の高さを決める

  • リストに並べるボタンなどには、Add Component>Layout>Layout Elementを付ける
  • Min Height(または Preferred Height)に高さ(例:60)を入れる

Layout Groupは、この値を見て項目の高さを決めます。

スクリプトでリストの項目を作る

アイテム名のリストから、ボタンを自動で並べてみましょう。

1. 項目のプレハブを作る

  1. Contentを右クリック>UI>Button – TextMeshProを作り、名前をItemRowにする
  2. ItemRowに、Add Component>Layout>Layout ElementでMin Heightを60にする
  3. 下の「ItemRow」スクリプトを作って、ItemRowにアタッチする
  4. ItemRowのInspectorで、Button欄に自分のButton、Label欄に子のText (TMP)を設定
  5. ItemRowをProjectウィンドウにドラッグしてプレハブにし、Hierarchyのほうは削除する(第7章の手順です)
using UnityEngine;
using UnityEngine.UI;
using TMPro;

// リストの1項目。自分のボタンが押されたら、自分のアイテム名をログに出す
public class ItemRow : MonoBehaviour
{
    [SerializeField] private Button button;
    [SerializeField] private TMP_Text label;

    private string itemName;

    void Awake()
    {
        button.onClick.AddListener(OnClicked);
    }

    void OnDestroy()
    {
        button.onClick.RemoveListener(OnClicked);
    }

    // 作ったあとに、表示する名前を設定する
    public void Setup(string newItemName)
    {
        itemName = newItemName;
        label.text = newItemName;
    }

    private void OnClicked()
    {
        Debug.Log("アイテムが選ばれた: " + itemName);
    }
}

2. 項目を並べるスクリプト

「ItemList」という名前でスクリプトを作り、Scroll Viewにアタッチします。

using UnityEngine;

public class ItemList : MonoBehaviour
{
    [SerializeField] private ItemRow itemRowPrefab;   // 項目のプレハブ
    [SerializeField] private Transform content;       // Scroll ViewのContent
    [SerializeField] private string[] itemNames =
    {
        "やくそう", "どくけしそう", "キメラのつばさ", "どうのつるぎ", "かわのたて",
        "たびびとのふく", "せいすい", "まほうのせいすい", "ちからのたね", "すばやさのたね"
    };

    void Start()
    {
        foreach (string itemName in itemNames)
        {
            // Contentの子として、項目を作る
            ItemRow row = Instantiate(itemRowPrefab, content);
            row.Setup(itemName);
        }
    }
}
  • Instantiate(プレハブ, 親)で、Contentの子として項目を作ります。Layout Groupが自動で並べてくれるので、位置を指定する必要はありません
  • プレハブの変数をItemRow型にしておくと、作った直後にSetupを呼べます
  • ItemListのInspectorで、Item Row PrefabにプレハブのItemRow、ContentにScroll ViewのContentを設定します

再生して、10個のアイテムが縦に並び、スクロールできて、押すとConsoleに名前が出れば成功!

スライム

項目を増やしたのに、スクロールできない・・・

フェアリー

ContentにContent Size Fitterが付いているか確認してみて!Contentの高さが伸びないと、窓より大きくならないからスクロールできないんだ

Grid Layout Groupでタイル状に並べる

アイテムのアイコンを並べるときなどは、Grid Layout Groupが便利です。

  • Cell Size:1マスの大きさ
  • Spacing:マスどうしのすき間
  • Constraint:Fixed Column Count:1行に並べる数を決める(4なら4列)

VerticalをGridに付け替えるだけで、同じItemListのスクリプトでタイル状のリストになります(そのときは、ItemRowのLayout Elementの高さより、GridのCell Sizeが優先されます)。

よくあるエラーと対処法

エラー:スクロールできない

  • 原因:Contentが窓(Viewport)より大きくなっていない
  • 対処法:ContentにContent Size Fitter(Vertical Fit:Preferred Size)を付ける。項目にLayout Elementで高さを付ける

エラー:項目が重なって表示される・高さが0になる

  • 原因:Layout GroupのControl Child SizeのHeightにチェックがあるのに、項目に高さの指定がない
  • 対処法:項目にLayout ElementのMin Heightを設定する。またはControl Child SizeのHeightのチェックを外す

エラー:リストの外に項目がはみ出して見える

  • 原因:ViewportのMask(はみ出しを隠すコンポーネント)が外れている
  • 対処法:ViewportにMask(またはRect Mask 2D)が付いているか確認する

エラー:項目の位置が手で動かせない

  • 原因:Layout Groupが位置を決めているため(正常な動き)
  • 対処法:位置を変えたいときは、Layout GroupのPaddingやSpacing、Child Alignmentで調整する

まとめ

  • Scroll View:Viewport(窓)の中のContent(中身)をスクロールさせる。項目はContentの子に入れる
  • Layout Group:Vertical / Horizontal / Gridで、子を自動で並べる
  • Content Size Fitter:中身に合わせてContentの大きさを変える
  • Instantiate(プレハブ, content)で、スクリプトから項目を増やせる

これで第9章のUIはおしまいです!次の第10章では、作ったゲームをビルドして、ほかの人に遊んでもらえる形にしていきます。

次のステップ

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次