【Unity】パネルとボタンで可変長のメニューを作る

投稿者: | 2020-12-28

ボタンをパネルの子にして、ボタンの数によってサイズの変わるメニューを作ってみました。

まずボタンとパネルのプレハブを作りました。パネルのサイズを決めて、ボタンにlayout Elementコンポーネントを付けます。余白ができるようにMin Widthを設定しました。

パネルにはVertical Layout Groupを追加しました。Spacingでボタン同士の隙間の長さを設定できます。Control Child Sizeのチェックをいれると、Layout Elementコンポーネントによってボタンのサイズが変わります。

パネルの左上の四角い図をクリックして出るメニューでシフトキーを押しながら左上を選択します。

するとパネルのピボットが左上になります。自動でPivotの値が(0, 1)になります。Pivotでは左下からの標準化された値を使うようです。

空のゲームオブジェクトに新規スクリプトを付けて複数のボタン、パネルのプレハブと、メニューを表示するシーン上のCanvasをアタッチしました。

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

public class ItemMenuPanel : MonoBehaviour
{
    [SerializeField] GameObject[] buttonPrefabs;
    [SerializeField] GameObject panelPrefab;
    [SerializeField] Canvas canvas;

    [SerializeField] float pivotOffset = 20f;


    static ItemMenuPanel instance;
    public static ItemMenuPanel GetInstance()
    {
        return instance;
    }

    private void Awake()
    {
        instance = this;
    }

    public void CreateMenu(Vector2 position, params int[] indexes)
    {
        // indexに対応するボタンがあるか確認
        for(int i = 0; i< indexes.Length; i++)
        {
            if(indexes[i] >= buttonPrefabs.Length)
            {
                return;
            }
        }

        // パネルの高さ
        float panelHeight = indexes.Length * 30f + (indexes.Length + 1) * 5f;

        // パネルを作る
        GameObject panel = Instantiate(panelPrefab, canvas.transform);
        RectTransform panelRectTransform = panel.GetComponent();

        // 高さを設定
        Vector2 size = panelRectTransform.sizeDelta;
        size.y = panelHeight;
        panelRectTransform.sizeDelta = size;

        // パネルの子としてボタンを作る
        for (int i = 0; i < indexes.Length; i++)
        {
            Instantiate(buttonPrefabs[indexes[i]], panel.transform);
        }

        // ピボットを少しずらす
        Vector2 pivot = panelRectTransform.pivot;       
        pivot.x += pivotOffset / size.x;
        pivot.y -= pivotOffset / size.y;
        panelRectTransform.pivot = pivot;

        // マウスカーソルの位置に移動
        panelRectTransform.position = position;
    }
}

静的メソッドで他のクラスからシーン上のインスタンスを得てメニューを作るメソッドを呼びます。その時の引数にマウスカーソルの位置とボタンの種類を渡します。

引数にparamsキーワードを前置きしているので、コンマ区切りで好きなだけ渡せます。配列を渡すこともできます。

//ItemMenuPanel.GetInstance().InstantiateMenu(Input.mousePosition, 0, 0, 1, 2, 1);

var r = UnityEngine.Random.Range(1,10);

int[] array = new int[r];
for(int n = 0; n < r; n++)
{
    array[n] = 0;
}
ItemMenuPanel.GetInstance().CreateMenu(Input.mousePosition, array);

パネルの高さはボタンの高さや余白のサイズそのまま使いますが、ピボットは標準化されているので、ずらしたい値をパネルのサイズで割ります。縦横がそれぞれ1のときに、補正値に対応する値を求めるだけです。

// ピボットを少しずらす
Vector2 pivot = panelRectTransform.pivot;       
pivot.x += pivotOffset / size.x;
pivot.y -= pivotOffset / size.y;
panelRectTransform.pivot = pivot;
ピボット位置の補正前
補正後

これで可変長のメニューができました。

コメントを残す

メールアドレスが公開されることはありません。