学習記事一覧 · Unity

【学習】Unity:アイテム所持とセーブ入門(第7回)― 増やして並べる:ItemsDialog とデータ反映

第6回1マスぶんItemButton ができました。

いま必要なのは、インベントリの格子OwnedItemsData.Instance に合わせて 埋める処理です。

書籍準拠のサンプルでは ItemsDialog.cs

  • Instantiate でスロットを必要数だけ用意する
  • 表示したタイミングOwnedItems の並び順から 各ボタンに割り当てる

を担当します。

シリーズ


今日のゴール

  • ヒエラルキー上のひな形 1個から buttonNumber - 1 回だけ Instantiate して同数のスロットにする
  • Toggle()自分自身の GameObject を表示/非表示し、開いたとき 必ずリストを再走査して ItemButton.OwnedItem を更新する
  • 所持の件数より多いインデックスnull を渡して 空スロットにする

前提

  • Item.ItemTypeOwnedItemsData.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 だけの自分用実装の場合は、同じ並び順で並べられるゲッターを用意するとよいです

発展アイデア

  • LayoutGroupScrollRect と組み合わせて スクロール可能なリストにする
  • 閉じるボタンToggle()SetActive(false) にひも付ける
  • Time.timeScale = 0 のときに UI が反応すること(第8回)を前提に試す

次に進む

アイテム欄本体ができたら、あとは ゲーム側のメニューから 開く/閉じるだけです。

第8回:Menu でポーズと UI を繋ぐ