Unity UI: Vertical Layout Group を活用したインベントリ一覧UIの実装(図解付き)
本文は Unity 6(6000系)+ uGUI 2.x を前提にしています。スマホ解像度(Canvas Scaler: 1080×1920相当)を想定。
目次
概要
インベントリのような縦リストは Vertical Layout Group を使うと配置とサイズ調整を自動化できます。要素の増減・ソート・フィルタにも強く、ScrollView と組み合わせるだけで堅牢なUIになります。
Vertical Layout Groupの基本
- 子オブジェクトを縦方向に整列するコンポーネント。
- Padding / Spacing / Alignment / Force Expand の4つが柱。
- Layout Element と組み合わせることで、各カードの高さや推奨サイズを明示できます。
Inspector詳細(図解)
配置と余白の考え方
[親 (Content)] ← Padding (内側余白)
├─ ItemCard #1
│
├─ (Spacing)
│
├─ ItemCard #2
│
├─ (Spacing)
│
└─ ItemCard #3
プロパティの意味と実戦値
区分 | 設定 | 役割 | 実戦の目安 |
---|---|---|---|
Padding | L/R/T/B | コンテナ内の余白 | L/R=16〜24, T/B=12〜20 |
Spacing | 数値 | 子要素同士の間隔 | 8〜16 |
Child Alignment | Upper/Middle/Lower × Left/Center/Right | 束全体の位置 | 一般的に Upper Left/Center |
Reverse Arrangement | On/Off | 並び順の反転 | チャット/ログ向け |
Control Child Size | Width/Height | 親が子のサイズを上書き | 幅=On, 高=On(固定高) |
Use Child Scale | Width/Height | 子のScale反映 | 原則Off |
Child Force Expand | Width/Height | 余白の強制配分 | 幅=On, 高=Off |
注記:固定高さにする場合、各カードの Layout Element → Preferred Height を設定します(例: 100〜140)。
最小プレハブ設計図
全体構成(Hierarchy)
InventoryScroll (Prefab)
└─ Viewport (Mask)
└─ Content ← Vertical Layout Group + Content Size Fitter
├─ ItemCard (Prefab)
├─ ItemCard
└─ ItemCard
Content 設定(スクショ差し込み位置)
- RectTransform: Anchor Min/Max = (0,1)-(1,1), Pivot=(0.5,1), SizeDelta.y=0
- Vertical Layout Group:
- Padding: L/R=16, T=12, B=12
- Spacing: 12
- Child Alignment: Upper Center(または Upper Left)
- Control Child Size: Width=On, Height=On
- Child Force Expand: Width=On, Height=Off
- Content Size Fitter: Horizontal=Unconstrained, Vertical=Preferred Size
スクリーンショットを挿入:Vertical Layout Group の Inspector(Content 用)
ItemCard 設計(最小)
ItemCard (Prefab)
├─ LeftIcon (optional)
└─ TextArea
├─ NameText (TMP)
└─ SubText (TMP)
- RectTransform: Anchor=Top Stretch, Pivot=(0.5,1), SizeDelta=(0,120)
- Layout Element: Preferred Height=120
- NameText: FontSize=42, Overflow=Ellipsis
- SubText: FontSize=32, Color=#666666
スクリーンショットを挿入:ItemCard の RectTransform / Layout Element / TMP 設定
実装コード(生成側・表示側)
InventoryListController(生成側)
using UnityEngine;
public class InventoryListController : MonoBehaviour
{
[SerializeField] RectTransform content; // Content
[SerializeField] GameObject itemCardPrefab; // ItemCard プレハブ
public void AddItem(string name, int count, string note = null)
{
var go = Instantiate(itemCardPrefab, content);
var card = go.GetComponent<ItemCardController>();
card.Setup(name, count, note);
}
}
ItemCardController(表示側)
using TMPro;
using UnityEngine;
public class ItemCardController : MonoBehaviour
{
[SerializeField] TMP_Text nameText;
[SerializeField] TMP_Text subText;
public void Setup(string itemName, int count, string note = null)
{
if (nameText) nameText.text = itemName;
if (subText) subText.text = $"x{count}" + (string.IsNullOrEmpty(note) ? "" : $"|{note}");
}
}
ItemCard (Prefab)
├─ LeftIcon (optional)
└─ TextArea
├─ NameText (TMP)
└─ SubText (TMP)
1. LeftIcon を 置く場合
- RectTransform: 固定サイズ (例: 100×100)
- Anchor: 左上固定 (Min/Max=(0,1)-(0,1), Pivot=(0,1))
- Image コンポーネントを付与(Preserve Aspect=ON)
- TextArea の Leftマージン を +120 に設定(アイコン幅+余白ぶん)
→ アイコン付きカード(例えば食品アイテムの写真)を表示するレイアウトに。
2. LeftIcon を 置かない場合
- LeftIcon オブジェクトを削除する、または SetActive(false) にする
- TextArea の Leftマージンを 0 に戻す(Stretchで幅いっぱいに広げる)
- この調整を ItemCardController の Setup() 内で分岐させると便利
public void Setup(string itemName, int count, string note = null, Sprite icon = null)
{
if (nameText) nameText.text = itemName;
if (subText) subText.text = $"x{count}" + (string.IsNullOrEmpty(note) ? "" : $"|{note}");
if (leftIconImage)
{
if (icon != null)
{
leftIconImage.sprite = icon;
leftIconImage.gameObject.SetActive(true);
// TextArea の Left=120 に設定
textArea.offsetMin = new Vector2(120, textArea.offsetMin.y);
}
else
{
leftIconImage.gameObject.SetActive(false);
// TextArea を左詰め
textArea.offsetMin = new Vector2(0, textArea.offsetMin.y);
}
}
}
3. 実運用の工夫
- LayoutGroup を使わず、Horizontal Layout Group で LeftIcon と TextArea を横並びにすると、アイコンの有無で自動調整される(推奨)。
- Horizontal Layout Group の設定
- Child Force Expand: Width=OFF, Height=ON
- LeftIcon が無ければその分スペースが縮む
- Horizontal Layout Group の設定
- この場合、スクリプト側で offset を切り替える必要がなくなる。
まとめ
- LeftIconがoptional なら:
- 簡単:スクリプトで TextArea の位置を切り替える
- おすすめ:Horizontal Layout Group を使ってアイコン有無を自然に調整
よくあるハマり/デバッグ
- 子の幅が伸びない:Control Child Size: Width または Child Force Expand: Width が Off。→ いずれか(多くは両方)On。
- 高さがバラつく:各カードの Layout Element に Preferred Height がない。→ 統一値を設定。
- スクロール範囲が合わない:Content Size Fitter(Vertical=Preferred)が不足/相互参照で無限再レイアウト。→ 親子のFitter構成を見直し。
- 大量更新直後に崩れる:最後に1回だけ
LayoutRebuilder.ForceRebuildLayoutImmediate(content)
。
拡張案(検索・ソート・アニメ・保存)
- 検索/フィルタ:
card.gameObject.SetActive(match)
後に1回 ForceRebuild。 - ソート:期限などで並べ替え →
transform.SetSiblingIndex(i)
。 - アニメ:DOTween でカード出現/削除アニメ(フェード+スケール)。
- 保存:PlayerPrefs に JSON で保存→起動時に復元して AddItem。
まとめ
- Vertical Layout Group はインベントリUIの定番。余白・行間・幅伸張をUI側で自動化し、実装を単純化できる。
- 最小プレハブ(Content / ItemCard)とシンプルな2スクリプトで、運用可能な縦リストを短時間で構築できる。
付録:可変高さカードの指針
- 固定高さ→一覧性・操作性が高い(推奨)。
- 可変高さ→情報量は増えるが視線移動が重くなる。TextArea に Content Size Fitter(Vertical=Preferred)/親の Height 制御はOffにして干渉回避。
訪問数 3 回, 今日の訪問数 5回
ディスカッション
コメント一覧
まだ、コメントがありません