短編RPG制作(Unity2D)【第28回】メニューの作成その6


メニューへの表示

持っているアイテムをメニュー画面に表示させます。
プレイヤーが持っているアイテムに応じて、表示を変更します。更新するタイミングはメニューボタンを押したときとします。(むやみに毎フレーム更新しても無駄が多いと思われます。)

Onenableメソッドは使える?

表示・非表示を切り替えるときには、便利なライフサイクルOnenableメソッドがあります。
このメソッドは、スクリプトが設定されているゲームオブジェクトがアクティブになった時に自動だけ呼び出されます。さらに、再度アクティブになった場合にも呼び出せます。ここがStartメソッドやAwakeメソッドと違う部分です。
これだけ聞くと、今回の用途にぴったりなのですが……メニューボタンを押した際に呼び出される処理を確認してみます。

using UnityEngine;

public class MenuButton : MonoBehaviour
{
    [SerializeField] private Canvas _canvas;
    private bool canvasEnable = false;

    public void OnClickMenuButton()
    {
        if (!canvasEnable)
        {
            _canvas.enabled = true;
            canvasEnable = true;
        }
        else
        {
            _canvas.enabled = false;
            canvasEnable = false;
        }
        
    }
}

このMenuButtonスクリプトでは、メニュー画面のCanvasコンポーネントを表示・非表示しています。ゲームオブジェクトではありません。
よって、Enableメソッドは反応しないで終わってしまいます。(コンポーネントにスクリプトはアタッチできませんしね。そもそも、Enableメソッドはシーン切り替え時に活躍するものみたいです。)
ここはおとなしく、ボタンそのものにメニュー更新操作を付けることにします。

メニュー画面の更新

所持アイテム数に応じて、メニューの表示を変更します。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MenuButton : MonoBehaviour
{
    [SerializeField] private PlayerStatus _playerStatus;
    [SerializeField] private Canvas _canvas;
    [SerializeField] private GameObject _panelItemIcon;
    [SerializeField] private GameObject _panelItemContent;
    [SerializeField] private Image imageItemIcon;
    [SerializeField] private Image imageItemContent;
    private bool canvasEnable = false;
    private List<ItemData> itemList;
    private List<int> itemPossessions;

    public void OnClickMenuButton()
    {
        if (!canvasEnable)
        {
            MenuUpdate();
            _canvas.enabled = true;
            canvasEnable = true;
        }
        else
        {
            _canvas.enabled = false;
            canvasEnable = false;
        }
        
    }

    // メニュー表示の更新
    private void MenuUpdate()
    {
        itemList = _playerStatus.GetItemList();
        itemPossessions = _playerStatus.GetItemPossessions();

        // すべての子オブジェクトを削除
        foreach (Transform child in _panelItemIcon.transform)
        {
            GameObject.Destroy(child.gameObject);
        }
        foreach (Transform child in _panelItemContent.transform)
        {
            GameObject.Destroy(child.gameObject);
        }

        for (int i = 0; i < itemList.Count; i++)
        {
            Instantiate(imageItemIcon, _panelItemIcon.transform);
            Instantiate(imageItemContent, _panelItemContent.transform);
        }


    }
}

結果は下のようになりました。

アイテム未所持状態
アイテム1種類所持状態

アイテムの所持種類数に合わせて、メニューの項目数を変化させることができました。

まとめ

UIを「instantiate」で生成するのは初めてだったので、子要素に設定するための引数が分からず結構時間がかかりました。
また、子オブジェクトの消去の仕方を知らなかったり、usingでの宣言を忘れていたり、そもそもメソッドをどこに書くか迷ったり……
最初に比べると複雑になってきて、もっといい書き方がある気がしてなりませんが、整理するのはもっと勉強してからということで。
次回は続きを実装していきます。まだ表示数を操作しただけなので、内容にとりかかります。


この記事が気に入ったらサポートをしてみませんか?