【学習】Unity:アイテム所持とセーブ入門(第7回)― 増やして並べる:ItemsDialog とデータ反映
第6回 で 1マスぶんの ItemButton ができました。
いま必要なのは、インベントリの格子を OwnedItemsData.Instance に合わせて 埋める処理です。
書籍準拠のサンプルでは ItemsDialog.cs が
Instantiateでスロットを必要数だけ用意する- 表示したタイミングで
OwnedItemsの並び順から 各ボタンに割り当てる
を担当します。
シリーズ
- 目次(00)
- 前回: 第6回
- 第7回(本記事):
ItemsDialog- 次回: 第8回:Menu でポーズと UI を繋ぐ
今日のゴール
- ヒエラルキー上のひな形 1個から
buttonNumber - 1回だけInstantiateして同数のスロットにする Toggle()で 自分自身の GameObject を表示/非表示し、開いたとき 必ずリストを再走査してItemButton.OwnedItemを更新する- 所持の件数より多いインデックスは
nullを渡して 空スロットにする
前提
Item.ItemTypeとOwnedItemsData.OwnedItemは、第5回 や 第4回 の流れとして既にある- シーン側に
ItemsDialogを張り付けた 親 GameObject。初回Prefabは ヒエラルキーまたは Prefab で 1 個だけ子に置いたItemButtonを[SerializeField] itemButtonに割り当てる
インスペクタで調整するとよい値
| フィールド | 意味 |
|---|---|
buttonNumber |
スロットの個数(例:15) |
itemButton |
複製する元の ItemButton |
完成コード
using UnityEngine;
public class ItemsDialog : MonoBehaviour
{
[SerializeField] private int buttonNumber = 15;
[SerializeField] private ItemButton itemButton;
private ItemButton[] _itemButtons;
private void Start()
{
// 初期状態は非表示
gameObject.SetActive(false);
// アイテム欄を必要な分だけ複製
for (var i = 0; i < buttonNumber - 1; i++)
{
Instantiate(itemButton, transform);
}
// 子要素のItemButtonを一括取得、保持しておく
_itemButtons = GetComponentsInChildren<ItemButton>();
}
/// <summary>
/// アイテム欄の表示/非表示を切り替えます。
/// </summary>
public void Toggle()
{
gameObject.SetActive(!gameObject.activeSelf);
if (gameObject.activeSelf)
{
// 表示された場合はアイテム欄をリフレッシュする
for (var i = 0; i < buttonNumber; i++)
{
// 各アイテムボタンに所持アイテム情報をセット
_itemButtons[i].OwnedItem = OwnedItemsData.Instance.OwnedItems.Length > i
? OwnedItemsData.Instance.OwnedItems[i]
: null;
}
}
}
}プログラムの流れ
Start
↓
まず自分を非表示
↓
元の Button を (buttonNumber-1) 回複製して子へ
↓
GetComponentsInChildren で ItemButton 配列をキャッシュ
Toggle が呼ばれる
↓
Active を反転
↓
表示になった?
↓ Yes
i = 0 .. buttonNumber-1 について
OwnedItems が i 番目にある → セット/なければ null重要ポイント
buttonNumberと_itemButtons.Lengthが食い違うとIndexOutOfRangeが出やすいです。授業では Prefab の子、Instantiate回数、配列サイズを一緒に確認します- 表示のたびにリフレッシュ … 実行中に
Addした内容を 確実に反映できる反面、リストが長いときは将来的に 差分だけ更新などの検討余地があります OwnedItemsが配列である前提(Lengthが使える)で、書籍サンプルの API に沿っています。第4回のようなListだけの自分用実装の場合は、同じ並び順で並べられるゲッターを用意するとよいです
発展アイデア
LayoutGroup/ScrollRectと組み合わせて スクロール可能なリストにする- 閉じるボタンも
Toggle()やSetActive(false)にひも付ける Time.timeScale = 0のときに UI が反応すること(第8回)を前提に試す
次に進む
アイテム欄本体ができたら、あとは ゲーム側のメニューから 開く/閉じるだけです。