NewUIでScrollRect内にボタンをC#で並べる

先日β版リリースされたUnity4.6で新しいUIが触れるようになりました。
早速、パズドラのダンジョン選択画面のような、スクロールエリア内に縦にずらーっとボタンが並ぶようなUIを作ってみます。
UnityエディタGUI上での作成方法は公式のチュートリアル動画で解説されているので、今回はC#から指定した任意の数だけボタンを並べられるようにしたチュートリアル動画を作りました。


フルスクリーンでHD画質でご覧ください。サンプルファイルのダウンロードはGitHub(https://github.com/trick7/unitynewui)からどうぞ。
※Unityそんなに使いこなせてないので、間違いあれば教えてください!!

UIは全てCanvas直下にあるべしとか、コンテンツスクロールはScrollRectコンポーネントを使えみたいな基本的なことは公式のチュートリアルで説明されているので、僕が声を大にして発表したいのは下の2点だけです。

ScrollRectの使い方

scroll3
・ScrollRectの対象として設定できるのは1オブジェクトだけなので、複数個のボタンをくるむような器となるオブジェクトが必要。
・ScrollRectは対象(content)の幅と高さを参照するが、対象(つまり器)が内包する子オブジェクトの幅や高さを考慮してくれないので、対象(content)の幅と高さをRectRransformから動的に変更してやる必要がある。

Button内のTextにC#でアクセスする方法

scroll2
Buttonの子オブジェクトとしてTextオブジェクトが最初から存在していて、そのTextオブジェクトにはText(Script)コンポーネントがアタッチされています。
これにアクセスするためには、C#冒頭で using UnityEngine.UI でインポートしないと、GetComponent()を取得できないので注意。

以上2点だけハマりましたが、公式フォーラムを読んで解決できました。
なのでチュートリアル動画まで作る必要なかったのですが、動画作るのにすごい時間かかったのでもし良かったらご覧ください。

参考までに、上の動画内でやっていることは以下の通りです。

1.Canvasを作る
Unityの新UIの構成要素はCanvasの中に格納されていることが必須ですので、Create>UI>Canvasで新規キャンバスを作成。

2.表示領域を作成
Canvasの子オブジェクトとして、Create>UI>Panelを選び、スクロールエリアの表示領域となるPanelオブジェクトを作成します。ここではScrollPanelという名前にしました。

3.コンテンツの器を作成
スクロール対象のコンテンツ(今回はたくさんのボタン達)をまとめて入れておくための器となるPanelオブジェクトを作成します。名前をContentPanelとしました。なぜ器が必要かというと、上で作ったScrollPanelはスクロール対象オブジェクトを1つだけ指定するようになっているので、ScrollPanel直下に複数個のボタンを置くのではなく、ContentPanelのように1つの器を用意する必要があるようです。
次に、この器の基準点を上端に指定し直します。インスペクタのRectTransformの部分で、AnchorのPreset指定を中央上端に指定し、AnchorsのPivotのYを1にしてから、PosX,PosY,PosZを全て0にすれば、見た目そのままでContentPanelのアンカーポイントを上端に設定できます。

4.ボタンを作成
Create>UI>Buttonにてボタンを作成します。名前はそのままButtonとしておきます。変な場所に作成されるかと思いますが、3と同様、インスペクタのRectTransformの部分で、AnchorPresetを中央上端に、AnchorsのPivotのYを1にしてから、PosX,PosY,PosZを全て0にすればScrollPanelの上端の位置にボタンがくると思います。
Projectパネル上で空のPrefab(名前をButtonとします)を作成し、今作ったヒエラルキー上のButtonをドラッグ&ドロップしてPrefab化し、ステージ上のButtonは消しておきます。
scroll4

5.コンポーネント&インスペクタ設定
2で作ったScrollPanelのインスペクタ上で、Add Component>UI>ScrollRectを作成、インスペクタ上のcontent項目に、スクロール対象となるContentPanelをドラッグ&ドロップします。
続いて同じくScrollPanelに対し、Add Component>UI>Maskでコンテンツ領域をScrollPanel自身の矩形でマスキングします。
新規にC#を作成し、名前を同名のScrollPanelとし、ヒエラルキーパネル上のScrollPanelにドロップして割り当てます。
MonoDevelopでC#を開き、以下のように記述します。

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

public class ScrollPanel : MonoBehaviour {
	public int numButtons = 14;
	public GameObject content;
	public GameObject buttonPrefab;
	// Use this for initialization
	void Start () {
		float btnHeight = 0;
		for (int i=0; i();
			//テキスト情報を変更
			btnText.text = "BUTTON"+i.ToString();
			//ボタンの位置を修正するためにRectTransformコンポーネントを取得
			RectTransform btnRectTrans = button.GetComponent();
			//ボタンの高さはRectTransformのsizeDeltaプロパティから取得できる
			btnHeight = btnRectTrans.sizeDelta.y;
			//ボタンの位置はlocalPositionで指定できる
			btnRectTrans.localPosition = new Vector2(0,-btnHeight*i);
		}
		//器であるcontentオブジェクトの高さを、内包するボタンの数に応じて伸長する
		RectTransform contentRectTrans = content.GetComponent ();
		contentRectTrans.sizeDelta = new Vector2 (GetComponent ().sizeDelta.x, btnHeight * numButtons);
	}
}

これでOK。
インスペクタ上で指定したボタンの数だけボタンが並び、ボタン内のテキストも差し替えできていて、破綻なくスクロールできるようになっていると思います。
scroll1
詳しくはビデオの方をご覧ください。

あと余談ですが、Unity4.6はまだベータ版なので、以前のバージョンと共存させたい場合は旧バージョンのアプリケーションディレクトリ名を変更してからインストールすればいいんですってよ。

参考リンク:
http://forum.unity3d.com/threads/scrollrect-runtime-content.263815/
http://forum.unity3d.com/threads/how-do-i-access-text-object-with-the-new-ui.263705/