ボタンをパネルの子にして、ボタンの数によってサイズの変わるメニューを作ってみました。
まずボタンとパネルのプレハブを作りました。パネルのサイズを決めて、ボタンに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;
これで可変長のメニューができました。